FileListTransfer.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "NativeFeatureIncludes.h"
  11. #if _RAKNET_SUPPORT_FileListTransfer==1 && _RAKNET_SUPPORT_FileOperations==1
  12. #include "FileListTransfer.h"
  13. #include "DS_HuffmanEncodingTree.h"
  14. #include "FileListTransferCBInterface.h"
  15. #include "StringCompressor.h"
  16. #include "FileList.h"
  17. #include "DS_Queue.h"
  18. #include "MessageIdentifiers.h"
  19. #include "RakNetTypes.h"
  20. #include "RakPeerInterface.h"
  21. #include "RakNetStatistics.h"
  22. #include "IncrementalReadInterface.h"
  23. #include "RakAssert.h"
  24. #include "RakAlloca.h"
  25. #ifdef _MSC_VER
  26. #pragma warning( push )
  27. #endif
  28. namespace RakNet
  29. {
  30. struct FLR_MemoryBlock
  31. {
  32. char *flrMemoryBlock;
  33. };
  34. struct FileListReceiver
  35. {
  36. FileListReceiver();
  37. ~FileListReceiver();
  38. FileListTransferCBInterface *downloadHandler;
  39. SystemAddress allowedSender;
  40. unsigned short setID;
  41. unsigned setCount;
  42. unsigned setTotalCompressedTransmissionLength;
  43. unsigned setTotalFinalLength;
  44. unsigned setTotalDownloadedLength;
  45. bool gotSetHeader;
  46. bool deleteDownloadHandler;
  47. bool isCompressed;
  48. int filesReceived;
  49. DataStructures::Map<unsigned int, FLR_MemoryBlock> pushedFiles;
  50. // Notifications
  51. unsigned int partLength;
  52. };
  53. } // namespace RakNet
  54. using namespace RakNet;
  55. FileListReceiver::FileListReceiver() {filesReceived=0; setTotalDownloadedLength=0; partLength=1; DataStructures::Map<unsigned int, FLR_MemoryBlock>::IMPLEMENT_DEFAULT_COMPARISON();}
  56. FileListReceiver::~FileListReceiver() {
  57. unsigned int i=0;
  58. for (i=0; i < pushedFiles.Size(); i++)
  59. rakFree_Ex(pushedFiles[i].flrMemoryBlock, _FILE_AND_LINE_ );
  60. }
  61. STATIC_FACTORY_DEFINITIONS(FileListTransfer,FileListTransfer)
  62. void FileListTransfer::FileToPushRecipient::DeleteThis(void)
  63. {
  64. //// filesToPushMutex.Lock();
  65. for (unsigned int j=0; j < filesToPush.Size(); j++)
  66. RakNet::OP_DELETE(filesToPush[j],_FILE_AND_LINE_);
  67. //// filesToPushMutex.Unlock();
  68. RakNet::OP_DELETE(this,_FILE_AND_LINE_);
  69. }
  70. void FileListTransfer::FileToPushRecipient::AddRef(void)
  71. {
  72. refCountMutex.Lock();
  73. ++refCount;
  74. refCountMutex.Unlock();
  75. }
  76. void FileListTransfer::FileToPushRecipient::Deref(void)
  77. {
  78. refCountMutex.Lock();
  79. --refCount;
  80. if (refCount==0)
  81. {
  82. refCountMutex.Unlock();
  83. DeleteThis();
  84. return;
  85. }
  86. refCountMutex.Unlock();
  87. }
  88. FileListTransfer::FileListTransfer()
  89. {
  90. setId=0;
  91. DataStructures::Map<unsigned short, FileListReceiver*>::IMPLEMENT_DEFAULT_COMPARISON();
  92. }
  93. FileListTransfer::~FileListTransfer()
  94. {
  95. threadPool.StopThreads();
  96. Clear();
  97. }
  98. void FileListTransfer::StartIncrementalReadThreads(int numThreads, int threadPriority)
  99. {
  100. (void) threadPriority;
  101. threadPool.StartThreads(numThreads, 0);
  102. }
  103. unsigned short FileListTransfer::SetupReceive(FileListTransferCBInterface *handler, bool deleteHandler, SystemAddress allowedSender)
  104. {
  105. if (rakPeerInterface && rakPeerInterface->GetConnectionState(allowedSender)!=IS_CONNECTED)
  106. return (unsigned short)-1;
  107. FileListReceiver *receiver;
  108. if (fileListReceivers.Has(setId))
  109. {
  110. receiver=fileListReceivers.Get(setId);
  111. receiver->downloadHandler->OnDereference();
  112. if (receiver->deleteDownloadHandler)
  113. RakNet::OP_DELETE(receiver->downloadHandler, _FILE_AND_LINE_);
  114. RakNet::OP_DELETE(receiver, _FILE_AND_LINE_);
  115. fileListReceivers.Delete(setId);
  116. }
  117. unsigned short oldId;
  118. receiver = RakNet::OP_NEW<FileListReceiver>( _FILE_AND_LINE_ );
  119. RakAssert(handler);
  120. receiver->downloadHandler=handler;
  121. receiver->allowedSender=allowedSender;
  122. receiver->gotSetHeader=false;
  123. receiver->deleteDownloadHandler=deleteHandler;
  124. receiver->setID=setId;
  125. fileListReceivers.Set(setId, receiver);
  126. oldId=setId;
  127. if (++setId==(unsigned short)-1)
  128. setId=0;
  129. return oldId;
  130. }
  131. void FileListTransfer::Send(FileList *fileList, RakNet::RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize)
  132. {
  133. for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
  134. fileList->AddCallback(fileListProgressCallbacks[flpcIndex]);
  135. unsigned int i, totalLength;
  136. RakNet::BitStream outBitstream;
  137. bool sendReference;
  138. const char *dataBlocks[2];
  139. int lengths[2];
  140. totalLength=0;
  141. for (i=0; i < fileList->fileList.Size(); i++)
  142. {
  143. const FileListNode &fileListNode = fileList->fileList[i];
  144. totalLength+=fileListNode.dataLengthBytes;
  145. }
  146. // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes
  147. bool anythingToWrite;
  148. outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER);
  149. outBitstream.Write(setID);
  150. anythingToWrite=fileList->fileList.Size()>0;
  151. outBitstream.Write(anythingToWrite);
  152. if (anythingToWrite)
  153. {
  154. outBitstream.WriteCompressed(fileList->fileList.Size());
  155. outBitstream.WriteCompressed(totalLength);
  156. if (rakPeer)
  157. rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
  158. else
  159. SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
  160. DataStructures::Queue<FileToPush*> filesToPush;
  161. for (i=0; i < fileList->fileList.Size(); i++)
  162. {
  163. sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0;
  164. if (sendReference)
  165. {
  166. FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(_FILE_AND_LINE_);
  167. fileToPush->fileListNode.context=fileList->fileList[i].context;
  168. fileToPush->setIndex=i;
  169. fileToPush->fileListNode.filename=fileList->fileList[i].filename;
  170. fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile;
  171. fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes;
  172. fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes;
  173. // fileToPush->systemAddress=recipient;
  174. //fileToPush->setID=setID;
  175. fileToPush->packetPriority=priority;
  176. fileToPush->orderingChannel=orderingChannel;
  177. fileToPush->currentOffset=0;
  178. fileToPush->incrementalReadInterface=_incrementalReadInterface;
  179. fileToPush->chunkSize=_chunkSize;
  180. filesToPush.Push(fileToPush,_FILE_AND_LINE_);
  181. }
  182. else
  183. {
  184. outBitstream.Reset();
  185. outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE);
  186. outBitstream << fileList->fileList[i].context;
  187. // outBitstream.Write(fileList->fileList[i].context);
  188. outBitstream.Write(setID);
  189. StringCompressor::Instance()->EncodeString(fileList->fileList[i].filename, 512, &outBitstream);
  190. outBitstream.WriteCompressed(i);
  191. outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes
  192. outBitstream.AlignWriteToByteBoundary();
  193. dataBlocks[0]=(char*) outBitstream.GetData();
  194. lengths[0]=outBitstream.GetNumberOfBytesUsed();
  195. dataBlocks[1]=fileList->fileList[i].data;
  196. lengths[1]=fileList->fileList[i].dataLengthBytes;
  197. SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
  198. }
  199. }
  200. if (filesToPush.IsEmpty()==false)
  201. {
  202. FileToPushRecipient *ftpr;
  203. fileToPushRecipientListMutex.Lock();
  204. for (unsigned int i=0; i < fileToPushRecipientList.Size(); i++)
  205. {
  206. if (fileToPushRecipientList[i]->systemAddress==recipient && fileToPushRecipientList[i]->setId==setId)
  207. {
  208. // ftpr=fileToPushRecipientList[i];
  209. // ftpr->AddRef();
  210. // break;
  211. RakAssert("setId already in use for this recipient" && 0);
  212. }
  213. }
  214. fileToPushRecipientListMutex.Unlock();
  215. //if (ftpr==0)
  216. //{
  217. ftpr = RakNet::OP_NEW<FileToPushRecipient>(_FILE_AND_LINE_);
  218. ftpr->systemAddress=recipient;
  219. ftpr->setId=setID;
  220. ftpr->refCount=2; // Allocated and in the list
  221. fileToPushRecipientList.Push(ftpr, _FILE_AND_LINE_);
  222. //}
  223. while (filesToPush.IsEmpty()==false)
  224. {
  225. ////ftpr->filesToPushMutex.Lock();
  226. ftpr->filesToPush.Push(filesToPush.Pop(), _FILE_AND_LINE_);
  227. ////ftpr->filesToPushMutex.Unlock();
  228. }
  229. // ftpr out of scope
  230. ftpr->Deref();
  231. SendIRIToAddress(recipient, setID);
  232. return;
  233. }
  234. else
  235. {
  236. for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
  237. fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID);
  238. }
  239. }
  240. else
  241. {
  242. for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
  243. fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID);
  244. if (rakPeer)
  245. rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
  246. else
  247. SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
  248. }
  249. }
  250. bool FileListTransfer::DecodeSetHeader(Packet *packet)
  251. {
  252. bool anythingToWrite=false;
  253. unsigned short setID;
  254. RakNet::BitStream inBitStream(packet->data, packet->length, false);
  255. inBitStream.IgnoreBits(8);
  256. inBitStream.Read(setID);
  257. FileListReceiver *fileListReceiver;
  258. if (fileListReceivers.Has(setID)==false)
  259. {
  260. // If this assert hits you didn't call SetupReceive
  261. #ifdef _DEBUG
  262. RakAssert(0);
  263. #endif
  264. return false;
  265. }
  266. fileListReceiver=fileListReceivers.Get(setID);
  267. if (fileListReceiver->allowedSender!=packet->systemAddress)
  268. {
  269. #ifdef _DEBUG
  270. RakAssert(0);
  271. #endif
  272. return false;
  273. }
  274. #ifdef _DEBUG
  275. RakAssert(fileListReceiver->gotSetHeader==false);
  276. #endif
  277. inBitStream.Read(anythingToWrite);
  278. if (anythingToWrite)
  279. {
  280. inBitStream.ReadCompressed(fileListReceiver->setCount);
  281. if (inBitStream.ReadCompressed(fileListReceiver->setTotalFinalLength))
  282. {
  283. fileListReceiver->setTotalCompressedTransmissionLength=fileListReceiver->setTotalFinalLength;
  284. fileListReceiver->gotSetHeader=true;
  285. return true;
  286. }
  287. }
  288. else
  289. {
  290. FileListTransferCBInterface::DownloadCompleteStruct dcs;
  291. dcs.setID=fileListReceiver->setID;
  292. dcs.numberOfFilesInThisSet=fileListReceiver->setCount;
  293. dcs.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
  294. dcs.senderSystemAddress=packet->systemAddress;
  295. dcs.senderGuid=packet->guid;
  296. if (fileListReceiver->downloadHandler->OnDownloadComplete(&dcs)==false)
  297. {
  298. fileListReceiver->downloadHandler->OnDereference();
  299. fileListReceivers.Delete(setID);
  300. if (fileListReceiver->deleteDownloadHandler)
  301. RakNet::OP_DELETE(fileListReceiver->downloadHandler, _FILE_AND_LINE_);
  302. RakNet::OP_DELETE(fileListReceiver, _FILE_AND_LINE_);
  303. }
  304. return true;
  305. }
  306. return false;
  307. }
  308. bool FileListTransfer::DecodeFile(Packet *packet, bool isTheFullFile)
  309. {
  310. FileListTransferCBInterface::OnFileStruct onFileStruct;
  311. RakNet::BitStream inBitStream(packet->data, packet->length, false);
  312. inBitStream.IgnoreBits(8);
  313. onFileStruct.senderSystemAddress=packet->systemAddress;
  314. onFileStruct.senderGuid=packet->guid;
  315. unsigned int partCount=0;
  316. unsigned int partTotal=0;
  317. unsigned int partLength=0;
  318. onFileStruct.fileData=0;
  319. if (isTheFullFile==false)
  320. {
  321. // Disable endian swapping on reading this, as it's generated locally in ReliabilityLayer.cpp
  322. inBitStream.ReadBits( (unsigned char* ) &partCount, BYTES_TO_BITS(sizeof(partCount)), true );
  323. inBitStream.ReadBits( (unsigned char* ) &partTotal, BYTES_TO_BITS(sizeof(partTotal)), true );
  324. inBitStream.ReadBits( (unsigned char* ) &partLength, BYTES_TO_BITS(sizeof(partLength)), true );
  325. inBitStream.IgnoreBits(8);
  326. // The header is appended to every chunk, which we continue to read after this statement flrMemoryBlock
  327. }
  328. inBitStream >> onFileStruct.context;
  329. // inBitStream.Read(onFileStruct.context);
  330. inBitStream.Read(onFileStruct.setID);
  331. FileListReceiver *fileListReceiver;
  332. if (fileListReceivers.Has(onFileStruct.setID)==false)
  333. {
  334. return false;
  335. }
  336. fileListReceiver=fileListReceivers.Get(onFileStruct.setID);
  337. if (fileListReceiver->allowedSender!=packet->systemAddress)
  338. {
  339. #ifdef _DEBUG
  340. RakAssert(0);
  341. #endif
  342. return false;
  343. }
  344. #ifdef _DEBUG
  345. RakAssert(fileListReceiver->gotSetHeader==true);
  346. #endif
  347. if (StringCompressor::Instance()->DecodeString(onFileStruct.fileName, 512, &inBitStream)==false)
  348. {
  349. #ifdef _DEBUG
  350. RakAssert(0);
  351. #endif
  352. return false;
  353. }
  354. inBitStream.ReadCompressed(onFileStruct.fileIndex);
  355. inBitStream.ReadCompressed(onFileStruct.byteLengthOfThisFile);
  356. onFileStruct.numberOfFilesInThisSet=fileListReceiver->setCount;
  357. onFileStruct.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
  358. if (isTheFullFile)
  359. {
  360. onFileStruct.bytesDownloadedForThisFile=onFileStruct.byteLengthOfThisFile;
  361. fileListReceiver->setTotalDownloadedLength+=onFileStruct.byteLengthOfThisFile;
  362. onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength;
  363. }
  364. else
  365. {
  366. onFileStruct.bytesDownloadedForThisFile=partLength*partCount;
  367. onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength+onFileStruct.bytesDownloadedForThisFile;
  368. }
  369. // User callback for this file.
  370. if (isTheFullFile)
  371. {
  372. inBitStream.AlignReadToByteBoundary();
  373. onFileStruct.fileData = (char*) rakMalloc_Ex( (size_t) onFileStruct.byteLengthOfThisFile, _FILE_AND_LINE_ );
  374. inBitStream.Read((char*)onFileStruct.fileData, onFileStruct.byteLengthOfThisFile);
  375. FileListTransferCBInterface::FileProgressStruct fps;
  376. fps.onFileStruct=&onFileStruct;
  377. fps.partCount=1;
  378. fps.partTotal=1;
  379. fps.dataChunkLength=onFileStruct.byteLengthOfThisFile;
  380. fps.firstDataChunk=onFileStruct.fileData;
  381. fps.iriDataChunk=onFileStruct.fileData;
  382. fps.allocateIrIDataChunkAutomatically=true;
  383. fps.iriWriteOffset=0;
  384. fps.senderSystemAddress=packet->systemAddress;
  385. fps.senderGuid=packet->guid;
  386. fileListReceiver->downloadHandler->OnFileProgress(&fps);
  387. // Got a complete file
  388. // Either we are using IncrementalReadInterface and it was a small file or
  389. // We are not using IncrementalReadInterface
  390. if (fileListReceiver->downloadHandler->OnFile(&onFileStruct))
  391. rakFree_Ex(onFileStruct.fileData, _FILE_AND_LINE_ );
  392. fileListReceiver->filesReceived++;
  393. // If this set is done, free the memory for it.
  394. if ((int) fileListReceiver->setCount==fileListReceiver->filesReceived)
  395. {
  396. FileListTransferCBInterface::DownloadCompleteStruct dcs;
  397. dcs.setID=fileListReceiver->setID;
  398. dcs.numberOfFilesInThisSet=fileListReceiver->setCount;
  399. dcs.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
  400. dcs.senderSystemAddress=packet->systemAddress;
  401. dcs.senderGuid=packet->guid;
  402. if (fileListReceiver->downloadHandler->OnDownloadComplete(&dcs)==false)
  403. {
  404. fileListReceiver->downloadHandler->OnDereference();
  405. if (fileListReceiver->deleteDownloadHandler)
  406. RakNet::OP_DELETE(fileListReceiver->downloadHandler, _FILE_AND_LINE_);
  407. fileListReceivers.Delete(onFileStruct.setID);
  408. RakNet::OP_DELETE(fileListReceiver, _FILE_AND_LINE_);
  409. }
  410. }
  411. }
  412. else
  413. {
  414. inBitStream.AlignReadToByteBoundary();
  415. char *firstDataChunk;
  416. unsigned int unreadBits = inBitStream.GetNumberOfUnreadBits();
  417. unsigned int unreadBytes = BITS_TO_BYTES(unreadBits);
  418. firstDataChunk=(char*) inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset());
  419. FileListTransferCBInterface::FileProgressStruct fps;
  420. fps.onFileStruct=&onFileStruct;
  421. fps.partCount=partCount;
  422. fps.partTotal=partTotal;
  423. fps.dataChunkLength=unreadBytes;
  424. fps.firstDataChunk=firstDataChunk;
  425. fps.iriDataChunk=0;
  426. fps.allocateIrIDataChunkAutomatically=true;
  427. fps.iriWriteOffset=0;
  428. fps.senderSystemAddress=packet->systemAddress;
  429. fps.senderGuid=packet->guid;
  430. // Remote system is sending a complete file, but the file is large enough that we get ID_PROGRESS_NOTIFICATION from the transport layer
  431. fileListReceiver->downloadHandler->OnFileProgress(&fps);
  432. }
  433. return true;
  434. }
  435. PluginReceiveResult FileListTransfer::OnReceive(Packet *packet)
  436. {
  437. switch (packet->data[0])
  438. {
  439. case ID_FILE_LIST_TRANSFER_HEADER:
  440. DecodeSetHeader(packet);
  441. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  442. case ID_FILE_LIST_TRANSFER_FILE:
  443. DecodeFile(packet, true);
  444. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  445. case ID_FILE_LIST_REFERENCE_PUSH:
  446. OnReferencePush(packet, true);
  447. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  448. case ID_FILE_LIST_REFERENCE_PUSH_ACK:
  449. OnReferencePushAck(packet);
  450. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  451. case ID_DOWNLOAD_PROGRESS:
  452. if (packet->length>sizeof(MessageID)+sizeof(unsigned int)*3)
  453. {
  454. if (packet->data[sizeof(MessageID)+sizeof(unsigned int)*3]==ID_FILE_LIST_TRANSFER_FILE)
  455. {
  456. DecodeFile(packet, false);
  457. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  458. }
  459. if (packet->data[sizeof(MessageID)+sizeof(unsigned int)*3]==ID_FILE_LIST_REFERENCE_PUSH)
  460. {
  461. OnReferencePush(packet, false);
  462. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  463. }
  464. }
  465. break;
  466. }
  467. return RR_CONTINUE_PROCESSING;
  468. }
  469. void FileListTransfer::OnRakPeerShutdown(void)
  470. {
  471. threadPool.StopThreads();
  472. threadPool.ClearInput();
  473. Clear();
  474. }
  475. void FileListTransfer::Clear(void)
  476. {
  477. unsigned i;
  478. for (i=0; i < fileListReceivers.Size(); i++)
  479. {
  480. fileListReceivers[i]->downloadHandler->OnDereference();
  481. if (fileListReceivers[i]->deleteDownloadHandler)
  482. RakNet::OP_DELETE(fileListReceivers[i]->downloadHandler, _FILE_AND_LINE_);
  483. RakNet::OP_DELETE(fileListReceivers[i], _FILE_AND_LINE_);
  484. }
  485. fileListReceivers.Clear();
  486. fileToPushRecipientListMutex.Lock();
  487. for (unsigned int i=0; i < fileToPushRecipientList.Size(); i++)
  488. {
  489. FileToPushRecipient *ftpr = fileToPushRecipientList[i];
  490. // Taken out of the list
  491. ftpr->Deref();
  492. }
  493. fileToPushRecipientList.Clear(false,_FILE_AND_LINE_);
  494. fileToPushRecipientListMutex.Unlock();
  495. //filesToPush.Clear(false, _FILE_AND_LINE_);
  496. }
  497. void FileListTransfer::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
  498. {
  499. (void) lostConnectionReason;
  500. (void) rakNetGUID;
  501. RemoveReceiver(systemAddress);
  502. }
  503. void FileListTransfer::CancelReceive(unsigned short setId)
  504. {
  505. if (fileListReceivers.Has(setId)==false)
  506. {
  507. #ifdef _DEBUG
  508. RakAssert(0);
  509. #endif
  510. return;
  511. }
  512. FileListReceiver *fileListReceiver=fileListReceivers.Get(setId);
  513. fileListReceiver->downloadHandler->OnDereference();
  514. if (fileListReceiver->deleteDownloadHandler)
  515. RakNet::OP_DELETE(fileListReceiver->downloadHandler, _FILE_AND_LINE_);
  516. RakNet::OP_DELETE(fileListReceiver, _FILE_AND_LINE_);
  517. fileListReceivers.Delete(setId);
  518. }
  519. void FileListTransfer::RemoveReceiver(SystemAddress systemAddress)
  520. {
  521. unsigned i;
  522. i=0;
  523. threadPool.LockInput();
  524. while (i < threadPool.InputSize())
  525. {
  526. if (threadPool.GetInputAtIndex(i).systemAddress==systemAddress)
  527. {
  528. threadPool.RemoveInputAtIndex(i);
  529. }
  530. else
  531. i++;
  532. }
  533. threadPool.UnlockInput();
  534. i=0;
  535. while (i < fileListReceivers.Size())
  536. {
  537. if (fileListReceivers[i]->allowedSender==systemAddress)
  538. {
  539. fileListReceivers[i]->downloadHandler->OnDereference();
  540. if (fileListReceivers[i]->deleteDownloadHandler)
  541. RakNet::OP_DELETE(fileListReceivers[i]->downloadHandler, _FILE_AND_LINE_);
  542. RakNet::OP_DELETE(fileListReceivers[i], _FILE_AND_LINE_);
  543. fileListReceivers.RemoveAtIndex(i);
  544. }
  545. else
  546. i++;
  547. }
  548. fileToPushRecipientListMutex.Lock();
  549. i=0;
  550. while (i < fileToPushRecipientList.Size())
  551. {
  552. if (fileToPushRecipientList[i]->systemAddress==systemAddress)
  553. {
  554. FileToPushRecipient *ftpr = fileToPushRecipientList[i];
  555. // Tell the user that this recipient was lost
  556. for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
  557. fileListProgressCallbacks[flpcIndex]->OnSendAborted(ftpr->systemAddress);
  558. fileToPushRecipientList.RemoveAtIndex(i);
  559. // Taken out of the list
  560. ftpr->Deref();
  561. }
  562. else
  563. {
  564. i++;
  565. }
  566. }
  567. fileToPushRecipientListMutex.Unlock();
  568. }
  569. bool FileListTransfer::IsHandlerActive(unsigned short setId)
  570. {
  571. return fileListReceivers.Has(setId);
  572. }
  573. void FileListTransfer::AddCallback(FileListProgress *cb)
  574. {
  575. if (cb==0)
  576. return;
  577. if (fileListProgressCallbacks.GetIndexOf(cb)==(unsigned int) -1)
  578. fileListProgressCallbacks.Push(cb, _FILE_AND_LINE_);
  579. }
  580. void FileListTransfer::RemoveCallback(FileListProgress *cb)
  581. {
  582. unsigned int idx = fileListProgressCallbacks.GetIndexOf(cb);
  583. if (idx!=(unsigned int) -1)
  584. fileListProgressCallbacks.RemoveAtIndex(idx);
  585. }
  586. void FileListTransfer::ClearCallbacks(void)
  587. {
  588. fileListProgressCallbacks.Clear(true, _FILE_AND_LINE_);
  589. }
  590. void FileListTransfer::GetCallbacks(DataStructures::List<FileListProgress*> &callbacks)
  591. {
  592. callbacks = fileListProgressCallbacks;
  593. }
  594. void FileListTransfer::Update(void)
  595. {
  596. unsigned i;
  597. i=0;
  598. while (i < fileListReceivers.Size())
  599. {
  600. if (fileListReceivers[i]->downloadHandler->Update()==false)
  601. {
  602. fileListReceivers[i]->downloadHandler->OnDereference();
  603. if (fileListReceivers[i]->deleteDownloadHandler)
  604. RakNet::OP_DELETE(fileListReceivers[i]->downloadHandler, _FILE_AND_LINE_);
  605. RakNet::OP_DELETE(fileListReceivers[i], _FILE_AND_LINE_);
  606. fileListReceivers.RemoveAtIndex(i);
  607. }
  608. else
  609. i++;
  610. }
  611. }
  612. void FileListTransfer::OnReferencePush(Packet *packet, bool isTheFullFile)
  613. {
  614. RakNet::BitStream refPushAck;
  615. if (isTheFullFile==false)
  616. {
  617. // 12/23/09 Why do I care about ID_DOWNLOAD_PROGRESS for reference pushes?
  618. // 2/16/2012 I care because a reference push is 16 megabytes by default. Also, if it is the last file "if (ftpr->filesToPush.Size()<2)" or total file size exceeds smallFileTotalSize it always sends a reference push.
  619. // return;
  620. }
  621. FileListTransferCBInterface::OnFileStruct onFileStruct;
  622. RakNet::BitStream inBitStream(packet->data, packet->length, false);
  623. inBitStream.IgnoreBits(8);
  624. unsigned int partCount=0;
  625. unsigned int partTotal=1;
  626. unsigned int partLength=0;
  627. onFileStruct.fileData=0;
  628. if (isTheFullFile==false)
  629. {
  630. // Disable endian swapping on reading this, as it's generated locally in ReliabilityLayer.cpp
  631. inBitStream.ReadBits( (unsigned char* ) &partCount, BYTES_TO_BITS(sizeof(partCount)), true );
  632. inBitStream.ReadBits( (unsigned char* ) &partTotal, BYTES_TO_BITS(sizeof(partTotal)), true );
  633. inBitStream.ReadBits( (unsigned char* ) &partLength, BYTES_TO_BITS(sizeof(partLength)), true );
  634. inBitStream.IgnoreBits(8);
  635. // The header is appended to every chunk, which we continue to read after this statement flrMemoryBlock
  636. }
  637. inBitStream >> onFileStruct.context;
  638. inBitStream.Read(onFileStruct.setID);
  639. // This is not a progress notification, it is actually the entire packet
  640. if (isTheFullFile==true)
  641. {
  642. refPushAck.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH_ACK);
  643. refPushAck.Write(onFileStruct.setID);
  644. SendUnified(&refPushAck,HIGH_PRIORITY, RELIABLE, 0, packet->systemAddress, false);
  645. }
  646. // inBitStream.Read(onFileStruct.context);
  647. FileListReceiver *fileListReceiver;
  648. if (fileListReceivers.Has(onFileStruct.setID)==false)
  649. {
  650. return;
  651. }
  652. fileListReceiver=fileListReceivers.Get(onFileStruct.setID);
  653. if (fileListReceiver->allowedSender!=packet->systemAddress)
  654. {
  655. #ifdef _DEBUG
  656. RakAssert(0);
  657. #endif
  658. return;
  659. }
  660. #ifdef _DEBUG
  661. RakAssert(fileListReceiver->gotSetHeader==true);
  662. #endif
  663. if (StringCompressor::Instance()->DecodeString(onFileStruct.fileName, 512, &inBitStream)==false)
  664. {
  665. #ifdef _DEBUG
  666. RakAssert(0);
  667. #endif
  668. return;
  669. }
  670. inBitStream.ReadCompressed(onFileStruct.fileIndex);
  671. inBitStream.ReadCompressed(onFileStruct.byteLengthOfThisFile);
  672. unsigned int offset;
  673. unsigned int chunkLength;
  674. inBitStream.ReadCompressed(offset);
  675. inBitStream.ReadCompressed(chunkLength);
  676. bool lastChunk=false;
  677. inBitStream.Read(lastChunk);
  678. bool finished = lastChunk && isTheFullFile;
  679. if (isTheFullFile==false)
  680. fileListReceiver->partLength=partLength;
  681. FLR_MemoryBlock mb;
  682. if (fileListReceiver->pushedFiles.Has(onFileStruct.fileIndex)==false)
  683. {
  684. mb.flrMemoryBlock=(char*) rakMalloc_Ex(onFileStruct.byteLengthOfThisFile, _FILE_AND_LINE_);
  685. fileListReceiver->pushedFiles.SetNew(onFileStruct.fileIndex, mb);
  686. }
  687. else
  688. {
  689. mb=fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex);
  690. }
  691. unsigned int unreadBits = inBitStream.GetNumberOfUnreadBits();
  692. unsigned int unreadBytes = BITS_TO_BYTES(unreadBits);
  693. unsigned int amountToRead;
  694. if (isTheFullFile)
  695. amountToRead=chunkLength;
  696. else
  697. amountToRead=unreadBytes;
  698. inBitStream.AlignReadToByteBoundary();
  699. FileListTransferCBInterface::FileProgressStruct fps;
  700. if (isTheFullFile)
  701. {
  702. if (mb.flrMemoryBlock)
  703. {
  704. // Either the very first block, or a subsequent block and allocateIrIDataChunkAutomatically was true for the first block
  705. memcpy(mb.flrMemoryBlock+offset, inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset()), amountToRead);
  706. fps.iriDataChunk=mb.flrMemoryBlock+offset;
  707. }
  708. else
  709. {
  710. // In here mb.flrMemoryBlock is null
  711. // This means the first block explicitly deallocated the memory, and no blocks will be permanently held by RakNet
  712. fps.iriDataChunk=(char*) inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset());
  713. }
  714. onFileStruct.bytesDownloadedForThisFile=offset+chunkLength;
  715. fileListReceiver->setTotalDownloadedLength+=chunkLength;
  716. onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength;
  717. }
  718. else
  719. {
  720. onFileStruct.bytesDownloadedForThisFile=offset+partLength*partCount;
  721. onFileStruct.bytesDownloadedForThisSet=fileListReceiver->setTotalDownloadedLength+partCount*partLength;
  722. fps.iriDataChunk=(char*) inBitStream.GetData()+BITS_TO_BYTES(inBitStream.GetReadOffset());
  723. }
  724. onFileStruct.numberOfFilesInThisSet=fileListReceiver->setCount;
  725. // onFileStruct.setTotalCompressedTransmissionLength=fileListReceiver->setTotalCompressedTransmissionLength;
  726. onFileStruct.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
  727. // Note: mb.flrMemoryBlock may be null here
  728. onFileStruct.fileData=mb.flrMemoryBlock;
  729. onFileStruct.senderSystemAddress=packet->systemAddress;
  730. onFileStruct.senderGuid=packet->guid;
  731. unsigned int totalNotifications;
  732. unsigned int currentNotificationIndex;
  733. if (chunkLength==0 || chunkLength==onFileStruct.byteLengthOfThisFile)
  734. totalNotifications=1;
  735. else
  736. totalNotifications = onFileStruct.byteLengthOfThisFile / chunkLength + 1;
  737. if (chunkLength==0)
  738. currentNotificationIndex = 0;
  739. else
  740. currentNotificationIndex = offset / chunkLength;
  741. fps.onFileStruct=&onFileStruct;
  742. fps.partCount=currentNotificationIndex;
  743. fps.partTotal=totalNotifications;
  744. fps.dataChunkLength=amountToRead;
  745. fps.firstDataChunk=mb.flrMemoryBlock;
  746. fps.allocateIrIDataChunkAutomatically=true;
  747. fps.onFileStruct->fileData=mb.flrMemoryBlock;
  748. fps.iriWriteOffset=offset;
  749. fps.senderSystemAddress=packet->systemAddress;
  750. fps.senderGuid=packet->guid;
  751. if (finished)
  752. {
  753. char *oldFileData=fps.onFileStruct->fileData;
  754. if (fps.partCount==0)
  755. fps.firstDataChunk=fps.iriDataChunk;
  756. if (fps.partTotal==1)
  757. fps.onFileStruct->fileData=fps.iriDataChunk;
  758. fileListReceiver->downloadHandler->OnFileProgress(&fps);
  759. // Incremental read interface sent us a file chunk
  760. // This is the last file chunk we were waiting for to consider the file done
  761. if (fileListReceiver->downloadHandler->OnFile(&onFileStruct))
  762. rakFree_Ex(oldFileData, _FILE_AND_LINE_ );
  763. fileListReceiver->pushedFiles.Delete(onFileStruct.fileIndex);
  764. fileListReceiver->filesReceived++;
  765. // If this set is done, free the memory for it.
  766. if ((int) fileListReceiver->setCount==fileListReceiver->filesReceived)
  767. {
  768. FileListTransferCBInterface::DownloadCompleteStruct dcs;
  769. dcs.setID=fileListReceiver->setID;
  770. dcs.numberOfFilesInThisSet=fileListReceiver->setCount;
  771. dcs.byteLengthOfThisSet=fileListReceiver->setTotalFinalLength;
  772. dcs.senderSystemAddress=packet->systemAddress;
  773. dcs.senderGuid=packet->guid;
  774. if (fileListReceiver->downloadHandler->OnDownloadComplete(&dcs)==false)
  775. {
  776. fileListReceiver->downloadHandler->OnDereference();
  777. fileListReceivers.Delete(onFileStruct.setID);
  778. if (fileListReceiver->deleteDownloadHandler)
  779. RakNet::OP_DELETE(fileListReceiver->downloadHandler, _FILE_AND_LINE_);
  780. RakNet::OP_DELETE(fileListReceiver, _FILE_AND_LINE_);
  781. }
  782. }
  783. }
  784. else
  785. {
  786. if (isTheFullFile)
  787. {
  788. // 12/23/09 Don't use OnReferencePush anymore, just use OnFileProgress
  789. fileListReceiver->downloadHandler->OnFileProgress(&fps);
  790. if (fps.allocateIrIDataChunkAutomatically==false)
  791. {
  792. rakFree_Ex(fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex).flrMemoryBlock, _FILE_AND_LINE_ );
  793. fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex).flrMemoryBlock=0;
  794. }
  795. }
  796. else
  797. {
  798. // This is a download progress notification for a file chunk using incremental read interface
  799. // We don't have all the data for this chunk yet
  800. totalNotifications = onFileStruct.byteLengthOfThisFile / fileListReceiver->partLength + 1;
  801. if (isTheFullFile==false)
  802. currentNotificationIndex = (offset+partCount*fileListReceiver->partLength) / fileListReceiver->partLength ;
  803. else
  804. currentNotificationIndex = (offset+chunkLength) / fileListReceiver->partLength ;
  805. unreadBytes = onFileStruct.byteLengthOfThisFile - ((currentNotificationIndex+1) * fileListReceiver->partLength);
  806. fps.partCount=currentNotificationIndex;
  807. fps.partTotal=totalNotifications;
  808. // 2/19/2013 Why was this check here? It prevent smaller progress notifications
  809. // if (rakPeerInterface)
  810. {
  811. // Thus chunk is incomplete
  812. fps.iriDataChunk=0;
  813. fileListReceiver->downloadHandler->OnFileProgress(&fps);
  814. }
  815. }
  816. }
  817. return;
  818. }
  819. namespace RakNet
  820. {
  821. /*
  822. SendIRIToAddress - executes from Send(). =
  823. 1, Find the recipient to send for
  824. 2. Send ID_FILE_LIST_TRANSFER_FILE for each small file in the queue of ifles to be sent
  825. 3. If the file we are working on is done, remove it from the list
  826. 4. Send ID_FILE_LIST_REFERENCE_PUSH for the file we are working on
  827. File sender:
  828. ID_FILE_LIST_REFERENCE_PUSH sent from end of SendIRIToAddressCB
  829. Recipient:
  830. send ID_FILE_LIST_REFERENCE_PUSH_ACK sent from OnReferencePush() when 2nd parameter is true.
  831. File sender:
  832. Got ID_FILE_LIST_REFERENCE_PUSH_ACK. Calls OnReferencePushAck, calls SendIRIToAddress, calls SendIRIToAddressCB
  833. */
  834. int SendIRIToAddressCB(FileListTransfer::ThreadData threadData, bool *returnOutput, void* perThreadData)
  835. {
  836. (void) perThreadData;
  837. FileListTransfer *fileListTransfer = threadData.fileListTransfer;
  838. SystemAddress systemAddress = threadData.systemAddress;
  839. unsigned short setId = threadData.setId;
  840. *returnOutput=false;
  841. // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this
  842. unsigned int bytesRead;
  843. const char *dataBlocks[2];
  844. int lengths[2];
  845. unsigned int smallFileTotalSize=0;
  846. RakNet::BitStream outBitstream;
  847. unsigned int ftpIndex;
  848. fileListTransfer->fileToPushRecipientListMutex.Lock();
  849. for (ftpIndex=0; ftpIndex < fileListTransfer->fileToPushRecipientList.Size(); ftpIndex++)
  850. {
  851. FileListTransfer::FileToPushRecipient *ftpr = fileListTransfer->fileToPushRecipientList[ftpIndex];
  852. // Referenced by both ftpr and list
  853. ftpr->AddRef();
  854. fileListTransfer->fileToPushRecipientListMutex.Unlock();
  855. if (ftpr->systemAddress==systemAddress && ftpr->setId==setId)
  856. {
  857. FileListTransfer::FileToPush *ftp;
  858. ////ftpr->filesToPushMutex.Lock();
  859. ftp = ftpr->filesToPush.Pop();
  860. ////ftpr->filesToPushMutex.Unlock();
  861. // Read and send chunk. If done, delete at this index
  862. void *buff = rakMalloc_Ex(ftp->chunkSize, _FILE_AND_LINE_);
  863. if (buff==0)
  864. {
  865. ////ftpr->filesToPushMutex.Lock();
  866. ftpr->filesToPush.PushAtHead(ftp,0,_FILE_AND_LINE_);
  867. ////ftpr->filesToPushMutex.Unlock();
  868. ftpr->Deref();
  869. notifyOutOfMemory(_FILE_AND_LINE_);
  870. return 0;
  871. }
  872. // Read the next file chunk
  873. bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context);
  874. bool done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead;
  875. while (done && ftp->currentOffset==0 && smallFileTotalSize<ftp->chunkSize)
  876. {
  877. ////ftpr->filesToPushMutex.Lock();
  878. // The reason for 2 is that ID_FILE_LIST_REFERENCE_PUSH gets ID_FILE_LIST_REFERENCE_PUSH_ACK. WIthout ID_FILE_LIST_REFERENCE_PUSH_ACK, SendIRIToAddressCB would not be called again
  879. if (ftpr->filesToPush.Size()<2)
  880. {
  881. ////ftpr->filesToPushMutex.Unlock();
  882. break;
  883. }
  884. ////ftpr->filesToPushMutex.Unlock();
  885. // 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
  886. outBitstream.Reset();
  887. outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE);
  888. // outBitstream.Write(ftp->fileListNode.context);
  889. outBitstream << ftp->fileListNode.context;
  890. outBitstream.Write(setId);
  891. StringCompressor::Instance()->EncodeString(ftp->fileListNode.filename, 512, &outBitstream);
  892. outBitstream.WriteCompressed(ftp->setIndex);
  893. outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes
  894. outBitstream.AlignWriteToByteBoundary();
  895. dataBlocks[0]=(char*) outBitstream.GetData();
  896. lengths[0]=outBitstream.GetNumberOfBytesUsed();
  897. dataBlocks[1]=(const char*) buff;
  898. lengths[1]=bytesRead;
  899. fileListTransfer->SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false);
  900. // LWS : fixed freed pointer reference
  901. // unsigned int chunkSize = ftp->chunkSize;
  902. RakNet::OP_DELETE(ftp,_FILE_AND_LINE_);
  903. smallFileTotalSize+=bytesRead;
  904. //done = bytesRead!=ftp->chunkSize;
  905. ////ftpr->filesToPushMutex.Lock();
  906. ftp = ftpr->filesToPush.Pop();
  907. ////ftpr->filesToPushMutex.Unlock();
  908. bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context);
  909. done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead;
  910. }
  911. outBitstream.Reset();
  912. outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH);
  913. // outBitstream.Write(ftp->fileListNode.context);
  914. outBitstream << ftp->fileListNode.context;
  915. outBitstream.Write(setId);
  916. StringCompressor::Instance()->EncodeString(ftp->fileListNode.filename, 512, &outBitstream);
  917. outBitstream.WriteCompressed(ftp->setIndex);
  918. outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes
  919. outBitstream.WriteCompressed(ftp->currentOffset);
  920. ftp->currentOffset+=bytesRead;
  921. outBitstream.WriteCompressed(bytesRead);
  922. outBitstream.Write(done);
  923. for (unsigned int flpcIndex=0; flpcIndex < fileListTransfer->fileListProgressCallbacks.Size(); flpcIndex++)
  924. fileListTransfer->fileListProgressCallbacks[flpcIndex]->OnFilePush(ftp->fileListNode.filename, ftp->fileListNode.fileLengthBytes, ftp->currentOffset-bytesRead, bytesRead, done, systemAddress, setId);
  925. dataBlocks[0]=(char*) outBitstream.GetData();
  926. lengths[0]=outBitstream.GetNumberOfBytesUsed();
  927. dataBlocks[1]=(char*) buff;
  928. lengths[1]=bytesRead;
  929. //rakPeerInterface->SendList(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, ftp->systemAddress, false);
  930. char orderingChannel = ftp->orderingChannel;
  931. PacketPriority packetPriority = ftp->packetPriority;
  932. // Mutex state: FileToPushRecipient (ftpr) has AddRef. fileToPushRecipientListMutex not locked.
  933. if (done)
  934. {
  935. // Done
  936. //unsigned short setId = ftp->setID;
  937. RakNet::OP_DELETE(ftp,_FILE_AND_LINE_);
  938. ////ftpr->filesToPushMutex.Lock();
  939. if (ftpr->filesToPush.Size()==0)
  940. {
  941. ////ftpr->filesToPushMutex.Unlock();
  942. for (unsigned int flpcIndex=0; flpcIndex < fileListTransfer->fileListProgressCallbacks.Size(); flpcIndex++)
  943. fileListTransfer->fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(systemAddress, setId);
  944. // Remove ftpr from fileToPushRecipientList
  945. fileListTransfer->RemoveFromList(ftpr);
  946. }
  947. else
  948. {
  949. ////ftpr->filesToPushMutex.Unlock();
  950. }
  951. }
  952. else
  953. {
  954. ////ftpr->filesToPushMutex.Lock();
  955. ftpr->filesToPush.PushAtHead(ftp,0,_FILE_AND_LINE_);
  956. ////ftpr->filesToPushMutex.Unlock();
  957. }
  958. // ftpr out of scope
  959. ftpr->Deref();
  960. // 2/12/2012 Moved this line at after the if (done) block above.
  961. // See http://www.jenkinssoftware.com/forum/index.php?topic=4768.msg19738#msg19738
  962. fileListTransfer->SendListUnified(dataBlocks,lengths,2, packetPriority, RELIABLE_ORDERED, orderingChannel, systemAddress, false);
  963. rakFree_Ex(buff, _FILE_AND_LINE_ );
  964. return 0;
  965. }
  966. else
  967. {
  968. ftpr->Deref();
  969. fileListTransfer->fileToPushRecipientListMutex.Lock();
  970. }
  971. }
  972. fileListTransfer->fileToPushRecipientListMutex.Unlock();
  973. return 0;
  974. }
  975. }
  976. void FileListTransfer::SendIRIToAddress(SystemAddress systemAddress, unsigned short setId)
  977. {
  978. ThreadData threadData;
  979. threadData.fileListTransfer=this;
  980. threadData.systemAddress=systemAddress;
  981. threadData.setId=setId;
  982. if (threadPool.WasStarted())
  983. {
  984. threadPool.AddInput(SendIRIToAddressCB, threadData);
  985. }
  986. else
  987. {
  988. bool doesNothing;
  989. SendIRIToAddressCB(threadData, &doesNothing, 0);
  990. }
  991. }
  992. void FileListTransfer::OnReferencePushAck(Packet *packet)
  993. {
  994. RakNet::BitStream inBitStream(packet->data, packet->length, false);
  995. inBitStream.IgnoreBits(8);
  996. unsigned short setId;
  997. inBitStream.Read(setId);
  998. SendIRIToAddress(packet->systemAddress, setId);
  999. }
  1000. void FileListTransfer::RemoveFromList(FileToPushRecipient *ftpr)
  1001. {
  1002. fileToPushRecipientListMutex.Lock();
  1003. for (unsigned int i=0; i < fileToPushRecipientList.Size(); i++)
  1004. {
  1005. if (fileToPushRecipientList[i]==ftpr)
  1006. {
  1007. fileToPushRecipientList.RemoveAtIndex(i);
  1008. // List no longer references
  1009. ftpr->Deref();
  1010. fileToPushRecipientListMutex.Unlock();
  1011. return;
  1012. }
  1013. }
  1014. fileToPushRecipientListMutex.Unlock();
  1015. }
  1016. unsigned int FileListTransfer::GetPendingFilesToAddress(SystemAddress recipient)
  1017. {
  1018. fileToPushRecipientListMutex.Lock();
  1019. for (unsigned int i=0; i < fileToPushRecipientList.Size(); i++)
  1020. {
  1021. if (fileToPushRecipientList[i]->systemAddress==recipient)
  1022. {
  1023. unsigned int size = fileToPushRecipientList[i]->filesToPush.Size();
  1024. fileToPushRecipientListMutex.Unlock();
  1025. return size;
  1026. }
  1027. }
  1028. fileToPushRecipientListMutex.Unlock();
  1029. return 0;
  1030. }
  1031. #ifdef _MSC_VER
  1032. #pragma warning( pop )
  1033. #endif
  1034. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号