DirectoryDeltaTransfer.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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_DirectoryDeltaTransfer==1 && _RAKNET_SUPPORT_FileOperations==1
  12. #include "DirectoryDeltaTransfer.h"
  13. #include "FileList.h"
  14. #include "StringCompressor.h"
  15. #include "RakPeerInterface.h"
  16. #include "FileListTransfer.h"
  17. #include "FileListTransferCBInterface.h"
  18. #include "BitStream.h"
  19. #include "MessageIdentifiers.h"
  20. #include "FileOperations.h"
  21. #include "IncrementalReadInterface.h"
  22. using namespace RakNet;
  23. #ifdef _MSC_VER
  24. #pragma warning( push )
  25. #endif
  26. class DDTCallback : public FileListTransferCBInterface
  27. {
  28. public:
  29. unsigned subdirLen;
  30. char outputSubdir[512];
  31. FileListTransferCBInterface *onFileCallback;
  32. DDTCallback() {}
  33. virtual ~DDTCallback() {}
  34. virtual bool OnFile(OnFileStruct *onFileStruct)
  35. {
  36. char fullPathToDir[1024];
  37. if (onFileStruct->fileName && onFileStruct->fileData && subdirLen < strlen(onFileStruct->fileName))
  38. {
  39. strcpy(fullPathToDir, outputSubdir);
  40. strcat(fullPathToDir, onFileStruct->fileName+subdirLen);
  41. WriteFileWithDirectories(fullPathToDir, (char*)onFileStruct->fileData, (unsigned int ) onFileStruct->byteLengthOfThisFile);
  42. }
  43. else
  44. fullPathToDir[0]=0;
  45. return onFileCallback->OnFile(onFileStruct);
  46. }
  47. virtual void OnFileProgress(FileProgressStruct *fps)
  48. {
  49. char fullPathToDir[1024];
  50. if (fps->onFileStruct->fileName && subdirLen < strlen(fps->onFileStruct->fileName))
  51. {
  52. strcpy(fullPathToDir, outputSubdir);
  53. strcat(fullPathToDir, fps->onFileStruct->fileName+subdirLen);
  54. }
  55. else
  56. fullPathToDir[0]=0;
  57. onFileCallback->OnFileProgress(fps);
  58. }
  59. virtual bool OnDownloadComplete(DownloadCompleteStruct *dcs)
  60. {
  61. return onFileCallback->OnDownloadComplete(dcs);
  62. }
  63. };
  64. STATIC_FACTORY_DEFINITIONS(DirectoryDeltaTransfer,DirectoryDeltaTransfer);
  65. DirectoryDeltaTransfer::DirectoryDeltaTransfer()
  66. {
  67. applicationDirectory[0]=0;
  68. fileListTransfer=0;
  69. availableUploads = RakNet::OP_NEW<FileList>( _FILE_AND_LINE_ );
  70. priority=HIGH_PRIORITY;
  71. orderingChannel=0;
  72. incrementalReadInterface=0;
  73. }
  74. DirectoryDeltaTransfer::~DirectoryDeltaTransfer()
  75. {
  76. RakNet::OP_DELETE(availableUploads, _FILE_AND_LINE_);
  77. }
  78. void DirectoryDeltaTransfer::SetFileListTransferPlugin(FileListTransfer *flt)
  79. {
  80. if (fileListTransfer)
  81. {
  82. DataStructures::List<FileListProgress*> fileListProgressList;
  83. fileListTransfer->GetCallbacks(fileListProgressList);
  84. unsigned int i;
  85. for (i=0; i < fileListProgressList.Size(); i++)
  86. availableUploads->RemoveCallback(fileListProgressList[i]);
  87. }
  88. fileListTransfer=flt;
  89. if (flt)
  90. {
  91. DataStructures::List<FileListProgress*> fileListProgressList;
  92. flt->GetCallbacks(fileListProgressList);
  93. unsigned int i;
  94. for (i=0; i < fileListProgressList.Size(); i++)
  95. availableUploads->AddCallback(fileListProgressList[i]);
  96. }
  97. else
  98. {
  99. availableUploads->ClearCallbacks();
  100. }
  101. }
  102. void DirectoryDeltaTransfer::SetApplicationDirectory(const char *pathToApplication)
  103. {
  104. if (pathToApplication==0 || pathToApplication[0]==0)
  105. applicationDirectory[0]=0;
  106. else
  107. {
  108. strncpy(applicationDirectory, pathToApplication, 510);
  109. if (applicationDirectory[strlen(applicationDirectory)-1]!='/' && applicationDirectory[strlen(applicationDirectory)-1]!='\\')
  110. strcat(applicationDirectory, "/");
  111. applicationDirectory[511]=0;
  112. }
  113. }
  114. void DirectoryDeltaTransfer::SetUploadSendParameters(PacketPriority _priority, char _orderingChannel)
  115. {
  116. priority=_priority;
  117. orderingChannel=_orderingChannel;
  118. }
  119. void DirectoryDeltaTransfer::AddUploadsFromSubdirectory(const char *subdir)
  120. {
  121. availableUploads->AddFilesFromDirectory(applicationDirectory, subdir, true, false, true, FileListNodeContext(0,0,0,0));
  122. }
  123. unsigned short DirectoryDeltaTransfer::DownloadFromSubdirectory(FileList &localFiles, const char *subdir, const char *outputSubdir, bool prependAppDirToOutputSubdir, SystemAddress host, FileListTransferCBInterface *onFileCallback, PacketPriority _priority, char _orderingChannel, FileListProgress *cb)
  124. {
  125. RakAssert(host!=UNASSIGNED_SYSTEM_ADDRESS);
  126. DDTCallback *transferCallback;
  127. localFiles.AddCallback(cb);
  128. // Prepare the callback data
  129. transferCallback = RakNet::OP_NEW<DDTCallback>( _FILE_AND_LINE_ );
  130. if (subdir && subdir[0])
  131. {
  132. transferCallback->subdirLen=(unsigned int)strlen(subdir);
  133. if (subdir[transferCallback->subdirLen-1]!='/' && subdir[transferCallback->subdirLen-1]!='\\')
  134. transferCallback->subdirLen++;
  135. }
  136. else
  137. transferCallback->subdirLen=0;
  138. if (prependAppDirToOutputSubdir)
  139. strcpy(transferCallback->outputSubdir, applicationDirectory);
  140. else
  141. transferCallback->outputSubdir[0]=0;
  142. if (outputSubdir)
  143. strcat(transferCallback->outputSubdir, outputSubdir);
  144. if (transferCallback->outputSubdir[strlen(transferCallback->outputSubdir)-1]!='/' && transferCallback->outputSubdir[strlen(transferCallback->outputSubdir)-1]!='\\')
  145. strcat(transferCallback->outputSubdir, "/");
  146. transferCallback->onFileCallback=onFileCallback;
  147. // Setup the transfer plugin to get the response to this download request
  148. unsigned short setId = fileListTransfer->SetupReceive(transferCallback, true, host);
  149. // Send to the host, telling it to process this request
  150. RakNet::BitStream outBitstream;
  151. outBitstream.Write((MessageID)ID_DDT_DOWNLOAD_REQUEST);
  152. outBitstream.Write(setId);
  153. StringCompressor::Instance()->EncodeString(subdir, 256, &outBitstream);
  154. StringCompressor::Instance()->EncodeString(outputSubdir, 256, &outBitstream);
  155. localFiles.Serialize(&outBitstream);
  156. SendUnified(&outBitstream, _priority, RELIABLE_ORDERED, _orderingChannel, host, false);
  157. return setId;
  158. }
  159. unsigned short DirectoryDeltaTransfer::DownloadFromSubdirectory(const char *subdir, const char *outputSubdir, bool prependAppDirToOutputSubdir, SystemAddress host, FileListTransferCBInterface *onFileCallback, PacketPriority _priority, char _orderingChannel, FileListProgress *cb)
  160. {
  161. FileList localFiles;
  162. // Get a hash of all the files that we already have (if any)
  163. localFiles.AddFilesFromDirectory(prependAppDirToOutputSubdir ? applicationDirectory : 0, outputSubdir, true, false, true, FileListNodeContext(0,0,0,0));
  164. return DownloadFromSubdirectory(localFiles, subdir, outputSubdir, prependAppDirToOutputSubdir, host, onFileCallback, _priority, _orderingChannel, cb);
  165. }
  166. void DirectoryDeltaTransfer::GenerateHashes(FileList &localFiles, const char *outputSubdir, bool prependAppDirToOutputSubdir)
  167. {
  168. localFiles.AddFilesFromDirectory(prependAppDirToOutputSubdir ? applicationDirectory : 0, outputSubdir, true, false, true, FileListNodeContext(0,0,0,0));
  169. }
  170. void DirectoryDeltaTransfer::ClearUploads(void)
  171. {
  172. availableUploads->Clear();
  173. }
  174. void DirectoryDeltaTransfer::OnDownloadRequest(Packet *packet)
  175. {
  176. char subdir[256];
  177. char remoteSubdir[256];
  178. RakNet::BitStream inBitstream(packet->data, packet->length, false);
  179. FileList remoteFileHash;
  180. FileList delta;
  181. unsigned short setId;
  182. inBitstream.IgnoreBits(8);
  183. inBitstream.Read(setId);
  184. StringCompressor::Instance()->DecodeString(subdir, 256, &inBitstream);
  185. StringCompressor::Instance()->DecodeString(remoteSubdir, 256, &inBitstream);
  186. if (remoteFileHash.Deserialize(&inBitstream)==false)
  187. {
  188. #ifdef _DEBUG
  189. RakAssert(0);
  190. #endif
  191. return;
  192. }
  193. availableUploads->GetDeltaToCurrent(&remoteFileHash, &delta, subdir, remoteSubdir);
  194. if (incrementalReadInterface==0)
  195. delta.PopulateDataFromDisk(applicationDirectory, true, false, true);
  196. else
  197. delta.FlagFilesAsReferences();
  198. // This will call the ddtCallback interface that was passed to FileListTransfer::SetupReceive on the remote system
  199. fileListTransfer->Send(&delta, rakPeerInterface, packet->systemAddress, setId, priority, orderingChannel, incrementalReadInterface, chunkSize);
  200. }
  201. PluginReceiveResult DirectoryDeltaTransfer::OnReceive(Packet *packet)
  202. {
  203. switch (packet->data[0])
  204. {
  205. case ID_DDT_DOWNLOAD_REQUEST:
  206. OnDownloadRequest(packet);
  207. return RR_STOP_PROCESSING_AND_DEALLOCATE;
  208. }
  209. return RR_CONTINUE_PROCESSING;
  210. }
  211. unsigned DirectoryDeltaTransfer::GetNumberOfFilesForUpload(void) const
  212. {
  213. return availableUploads->fileList.Size();
  214. }
  215. void DirectoryDeltaTransfer::SetDownloadRequestIncrementalReadInterface(IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize)
  216. {
  217. incrementalReadInterface=_incrementalReadInterface;
  218. chunkSize=_chunkSize;
  219. }
  220. #ifdef _MSC_VER
  221. #pragma warning( pop )
  222. #endif
  223. #endif // _RAKNET_SUPPORT_*
粤ICP备19079148号