SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DirectoryDeltaTransfer.cpp
Go to the documentation of this file.
1 /*
2 * Original work: 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 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/NativeFeatureIncludes.h"
17 #if _RAKNET_SUPPORT_DirectoryDeltaTransfer==1 && _RAKNET_SUPPORT_FileOperations==1
18
19 #include "slikenet/DirectoryDeltaTransfer.h"
20 #include "slikenet/FileList.h"
21 #include "slikenet/StringCompressor.h"
22 #include "slikenet/peerinterface.h"
23 #include "slikenet/FileListTransfer.h"
24 #include "slikenet/FileListTransferCBInterface.h"
25 #include "slikenet/BitStream.h"
26 #include "slikenet/MessageIdentifiers.h"
27 #include "slikenet/FileOperations.h"
28 #include "slikenet/IncrementalReadInterface.h"
29 #include "slikenet/linux_adapter.h"
30 #include "slikenet/osx_adapter.h"
31
32 using namespace SLNet;
33
34 class DDTCallback : public FileListTransferCBInterface
35 {
36 public:
37 unsigned subdirLen;
38 char outputSubdir[512];
39 FileListTransferCBInterface *onFileCallback;
40
41 DDTCallback() {}
42 virtual ~DDTCallback() {}
43
44 virtual bool OnFile(OnFileStruct *onFileStruct)
45 {
46 char fullPathToDir[1024];
47
48 if (onFileStruct->fileData && subdirLen < strlen(onFileStruct->fileName))
49 {
50 strcpy_s(fullPathToDir, outputSubdir);
51 strcat_s(fullPathToDir, onFileStruct->fileName+subdirLen);
52 WriteFileWithDirectories(fullPathToDir, (char*)onFileStruct->fileData, (unsigned int ) onFileStruct->byteLengthOfThisFile);
53 }
54 else
55 fullPathToDir[0]=0;
56
57 return onFileCallback->OnFile(onFileStruct);
58 }
59
60 virtual void OnFileProgress(FileProgressStruct *fps)
61 {
62 char fullPathToDir[1024];
63
64 if (subdirLen < strlen(fps->onFileStruct->fileName))
65 {
66 strcpy_s(fullPathToDir, outputSubdir);
67 strcat_s(fullPathToDir, fps->onFileStruct->fileName+subdirLen);
68 }
69 else
70 fullPathToDir[0]=0;
71
72 onFileCallback->OnFileProgress(fps);
73 }
74 virtual bool OnDownloadComplete(DownloadCompleteStruct *dcs)
75 {
76 return onFileCallback->OnDownloadComplete(dcs);
77 }
78 };
79
80 STATIC_FACTORY_DEFINITIONS(DirectoryDeltaTransfer,DirectoryDeltaTransfer);
81
82 DirectoryDeltaTransfer::DirectoryDeltaTransfer()
83 {
84 applicationDirectory[0]=0;
85 fileListTransfer=0;
86 availableUploads = SLNet::OP_NEW<FileList>( _FILE_AND_LINE_ );
87 priority=HIGH_PRIORITY;
88 orderingChannel=0;
89 incrementalReadInterface=0;
90 }
91 DirectoryDeltaTransfer::~DirectoryDeltaTransfer()
92 {
93 SLNet::OP_DELETE(availableUploads, _FILE_AND_LINE_);
94 }
95 void DirectoryDeltaTransfer::SetFileListTransferPlugin(FileListTransfer *flt)
96 {
97 if (fileListTransfer)
98 {
99 DataStructures::List<FileListProgress*> fileListProgressList;
100 fileListTransfer->GetCallbacks(fileListProgressList);
101 unsigned int i;
102 for (i=0; i < fileListProgressList.Size(); i++)
103 availableUploads->RemoveCallback(fileListProgressList[i]);
104 }
105
106 fileListTransfer=flt;
107
108 if (flt)
109 {
110 DataStructures::List<FileListProgress*> fileListProgressList;
111 flt->GetCallbacks(fileListProgressList);
112 unsigned int i;
113 for (i=0; i < fileListProgressList.Size(); i++)
114 availableUploads->AddCallback(fileListProgressList[i]);
115 }
116 else
117 {
118 availableUploads->ClearCallbacks();
119 }
120 }
121 void DirectoryDeltaTransfer::SetApplicationDirectory(const char *pathToApplication)
122 {
123 if (pathToApplication==0 || pathToApplication[0]==0)
124 applicationDirectory[0]=0;
125 else
126 {
127 strncpy_s(applicationDirectory, pathToApplication, 510);
128 if (applicationDirectory[strlen(applicationDirectory)-1]!='/' && applicationDirectory[strlen(applicationDirectory)-1]!='\\')
129 strcat_s(applicationDirectory, "/");
130 applicationDirectory[511]=0;
131 }
132 }
133 void DirectoryDeltaTransfer::SetUploadSendParameters(PacketPriority _priority, char _orderingChannel)
134 {
135 priority=_priority;
136 orderingChannel=_orderingChannel;
137 }
138 void DirectoryDeltaTransfer::AddUploadsFromSubdirectory(const char *subdir)
139 {
140 availableUploads->AddFilesFromDirectory(applicationDirectory, subdir, true, false, true, FileListNodeContext(0,0,0,0));
141 }
142 unsigned short DirectoryDeltaTransfer::DownloadFromSubdirectory(FileList &localFiles, const char *subdir, const char *outputSubdir, bool prependAppDirToOutputSubdir, SystemAddress host, FileListTransferCBInterface *onFileCallback, PacketPriority _priority, char _orderingChannel, FileListProgress *cb)
143 {
144 RakAssert(host!=UNASSIGNED_SYSTEM_ADDRESS);
145
146 DDTCallback *transferCallback;
147
148 localFiles.AddCallback(cb);
149
150 // Prepare the callback data
151 transferCallback = SLNet::OP_NEW<DDTCallback>( _FILE_AND_LINE_ );
152 if (subdir && subdir[0])
153 {
154 transferCallback->subdirLen=(unsigned int)strlen(subdir);
155 if (subdir[transferCallback->subdirLen-1]!='/' && subdir[transferCallback->subdirLen-1]!='\\')
156 transferCallback->subdirLen++;
157 }
158 else
159 transferCallback->subdirLen=0;
160 if (prependAppDirToOutputSubdir)
161 strcpy_s(transferCallback->outputSubdir, applicationDirectory);
162 else
163 transferCallback->outputSubdir[0]=0;
164 if (outputSubdir)
165 strcat_s(transferCallback->outputSubdir, outputSubdir);
166 if (transferCallback->outputSubdir[strlen(transferCallback->outputSubdir)-1]!='/' && transferCallback->outputSubdir[strlen(transferCallback->outputSubdir)-1]!='\\')
167 strcat_s(transferCallback->outputSubdir, "/");
168 transferCallback->onFileCallback=onFileCallback;
169
170 // Setup the transfer plugin to get the response to this download request
171 unsigned short setId = fileListTransfer->SetupReceive(transferCallback, true, host);
172
173 // Send to the host, telling it to process this request
174 SLNet::BitStream outBitstream;
175 outBitstream.Write((MessageID)ID_DDT_DOWNLOAD_REQUEST);
176 outBitstream.Write(setId);
177 StringCompressor::Instance()->EncodeString(subdir, 256, &outBitstream);
178 StringCompressor::Instance()->EncodeString(outputSubdir, 256, &outBitstream);
179 localFiles.Serialize(&outBitstream);
180 SendUnified(&outBitstream, _priority, RELIABLE_ORDERED, _orderingChannel, host, false);
181
182 return setId;
183 }
184 unsigned short DirectoryDeltaTransfer::DownloadFromSubdirectory(const char *subdir, const char *outputSubdir, bool prependAppDirToOutputSubdir, SystemAddress host, FileListTransferCBInterface *onFileCallback, PacketPriority _priority, char _orderingChannel, FileListProgress *cb)
185 {
186 FileList localFiles;
187 // Get a hash of all the files that we already have (if any)
188 localFiles.AddFilesFromDirectory(prependAppDirToOutputSubdir ? applicationDirectory : 0, outputSubdir, true, false, true, FileListNodeContext(0,0,0,0));
189 return DownloadFromSubdirectory(localFiles, subdir, outputSubdir, prependAppDirToOutputSubdir, host, onFileCallback, _priority, _orderingChannel, cb);
190 }
191 void DirectoryDeltaTransfer::GenerateHashes(FileList &localFiles, const char *outputSubdir, bool prependAppDirToOutputSubdir)
192 {
193 localFiles.AddFilesFromDirectory(prependAppDirToOutputSubdir ? applicationDirectory : 0, outputSubdir, true, false, true, FileListNodeContext(0,0,0,0));
194 }
195 void DirectoryDeltaTransfer::ClearUploads(void)
196 {
197 availableUploads->Clear();
198 }
199 void DirectoryDeltaTransfer::OnDownloadRequest(Packet *packet)
200 {
201 char subdir[256];
202 char remoteSubdir[256];
203 SLNet::BitStream inBitstream(packet->data, packet->length, false);
204 FileList remoteFileHash;
205 FileList delta;
206 unsigned short setId;
207 inBitstream.IgnoreBits(8);
208 inBitstream.Read(setId);
209 StringCompressor::Instance()->DecodeString(subdir, 256, &inBitstream);
210 StringCompressor::Instance()->DecodeString(remoteSubdir, 256, &inBitstream);
211 if (remoteFileHash.Deserialize(&inBitstream)==false)
212 {
213 #ifdef _DEBUG
214 RakAssert(0);
215 #endif
216 return;
217 }
218
219 availableUploads->GetDeltaToCurrent(&remoteFileHash, &delta, subdir, remoteSubdir);
220 if (incrementalReadInterface==0)
221 delta.PopulateDataFromDisk(applicationDirectory, true, false, true);
222 else
223 delta.FlagFilesAsReferences();
224
225 // This will call the ddtCallback interface that was passed to FileListTransfer::SetupReceive on the remote system
226 fileListTransfer->Send(&delta, rakPeerInterface, packet->systemAddress, setId, priority, orderingChannel, incrementalReadInterface, chunkSize);
227 }
228 PluginReceiveResult DirectoryDeltaTransfer::OnReceive(Packet *packet)
229 {
230 switch (packet->data[0])
231 {
232 case ID_DDT_DOWNLOAD_REQUEST:
233 OnDownloadRequest(packet);
234 return RR_STOP_PROCESSING_AND_DEALLOCATE;
235 }
236
237 return RR_CONTINUE_PROCESSING;
238 }
239
240 unsigned DirectoryDeltaTransfer::GetNumberOfFilesForUpload(void) const
241 {
242 return availableUploads->fileList.Size();
243 }
244
245 void DirectoryDeltaTransfer::SetDownloadRequestIncrementalReadInterface(IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize)
246 {
247 incrementalReadInterface=_incrementalReadInterface;
248 chunkSize=_chunkSize;
249 }
250
251 #endif // _RAKNET_SUPPORT_*