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

DirectoryDeltaTransfer.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_DirectoryDeltaTransfer==1
00003 
00004 #include "DirectoryDeltaTransfer.h"
00005 #include "FileList.h"
00006 #include "StringCompressor.h"
00007 #include "RakPeerInterface.h"
00008 #include "FileListTransfer.h"
00009 #include "FileListTransferCBInterface.h"
00010 #include "BitStream.h"
00011 #include "MessageIdentifiers.h"
00012 #include "FileOperations.h"
00013 #include "IncrementalReadInterface.h"
00014 
00015 #ifdef _MSC_VER
00016 #pragma warning( push )
00017 #endif
00018 
00019 class DDTCallback : public FileListTransferCBInterface
00020 {
00021 public:
00022         unsigned subdirLen;
00023         char outputSubdir[512];
00024         FileListTransferCBInterface *onFileCallback;
00025 
00026         DDTCallback() {}
00027         virtual ~DDTCallback() {}
00028 
00029         virtual bool OnFile(OnFileStruct *onFileStruct)
00030         {
00031                 char fullPathToDir[1024];
00032 
00033                 if (onFileStruct->fileName && onFileStruct->fileData && subdirLen < strlen(onFileStruct->fileName))
00034                 {
00035                         strcpy(fullPathToDir, outputSubdir);
00036                         strcat(fullPathToDir, onFileStruct->fileName+subdirLen);
00037                         WriteFileWithDirectories(fullPathToDir, (char*)onFileStruct->fileData, (unsigned int ) onFileStruct->byteLengthOfThisFile);
00038                 }
00039                 else
00040                         fullPathToDir[0]=0;
00041 
00042                 return onFileCallback->OnFile(onFileStruct);
00043         }
00044 
00045         virtual void OnFileProgress(FileProgressStruct *fps)
00046         {
00047                 char fullPathToDir[1024];
00048 
00049                 if (fps->onFileStruct->fileName && subdirLen < strlen(fps->onFileStruct->fileName))
00050                 {
00051                         strcpy(fullPathToDir, outputSubdir);
00052                         strcat(fullPathToDir, fps->onFileStruct->fileName+subdirLen);
00053                 }
00054                 else
00055                         fullPathToDir[0]=0;
00056 
00057                 onFileCallback->OnFileProgress(fps);
00058         }
00059         virtual bool OnDownloadComplete(void)
00060         {
00061                 return onFileCallback->OnDownloadComplete();
00062         }
00063 };
00064 
00065 DirectoryDeltaTransfer::DirectoryDeltaTransfer()
00066 {
00067         applicationDirectory[0]=0;
00068         fileListTransfer=0;
00069         availableUploads = RakNet::OP_NEW<FileList>( __FILE__, __LINE__ );
00070         priority=HIGH_PRIORITY;
00071         orderingChannel=0;
00072         incrementalReadInterface=0;
00073         compressOutgoingSends=false;
00074 }
00075 DirectoryDeltaTransfer::~DirectoryDeltaTransfer()
00076 {
00077         RakNet::OP_DELETE(availableUploads, __FILE__, __LINE__);
00078 }
00079 void DirectoryDeltaTransfer::SetFileListTransferPlugin(FileListTransfer *flt)
00080 {
00081         fileListTransfer=flt;
00082         if (flt)
00083                 availableUploads->SetCallback(flt->GetCallback());
00084         else
00085                 availableUploads->SetCallback(0);
00086 }
00087 void DirectoryDeltaTransfer::SetApplicationDirectory(const char *pathToApplication)
00088 {
00089         if (pathToApplication==0 || pathToApplication[0]==0)
00090                 applicationDirectory[0]=0;
00091         else
00092         {
00093                 strncpy(applicationDirectory, pathToApplication, 510);
00094                 if (applicationDirectory[strlen(applicationDirectory)-1]!='/' && applicationDirectory[strlen(applicationDirectory)-1]!='\\')
00095                         strcat(applicationDirectory, "/");
00096                 applicationDirectory[511]=0;
00097         }
00098 }
00099 void DirectoryDeltaTransfer::SetUploadSendParameters(PacketPriority _priority, char _orderingChannel)
00100 {
00101         priority=_priority;
00102         orderingChannel=_orderingChannel;
00103 }
00104 void DirectoryDeltaTransfer::AddUploadsFromSubdirectory(const char *subdir)
00105 {
00106         availableUploads->AddFilesFromDirectory(applicationDirectory, subdir, true, false, true, FileListNodeContext(0,0));
00107 }
00108 unsigned short DirectoryDeltaTransfer::DownloadFromSubdirectory(const char *subdir, const char *outputSubdir, bool prependAppDirToOutputSubdir, SystemAddress host, FileListTransferCBInterface *onFileCallback, PacketPriority _priority, char _orderingChannel, FileListProgress *cb)
00109 {
00110 //      if (rakPeerInterface->IsConnected(host)==false)
00111 //              return (unsigned short) -1;
00112         RakAssert(host!=UNASSIGNED_SYSTEM_ADDRESS);
00113 
00114         DDTCallback *transferCallback;
00115         FileList localFiles;
00116         localFiles.SetCallback(cb);
00117         // Get a hash of all the files that we already have (if any)
00118         localFiles.AddFilesFromDirectory(prependAppDirToOutputSubdir ? applicationDirectory : 0, outputSubdir, true, false, true, FileListNodeContext(0,0));
00119 
00120         // Prepare the callback data
00121         transferCallback = RakNet::OP_NEW<DDTCallback>( __FILE__, __LINE__ );
00122         if (subdir && subdir[0])
00123         {
00124                 transferCallback->subdirLen=(unsigned int)strlen(subdir);
00125                 if (subdir[transferCallback->subdirLen-1]!='/' && subdir[transferCallback->subdirLen-1]!='\\')
00126                         transferCallback->subdirLen++;
00127         }
00128         else
00129                 transferCallback->subdirLen=0;
00130         if (prependAppDirToOutputSubdir)
00131                 strcpy(transferCallback->outputSubdir, applicationDirectory);
00132         else
00133                 transferCallback->outputSubdir[0]=0;
00134         if (outputSubdir)
00135                 strcat(transferCallback->outputSubdir, outputSubdir);
00136         if (transferCallback->outputSubdir[strlen(transferCallback->outputSubdir)-1]!='/' && transferCallback->outputSubdir[strlen(transferCallback->outputSubdir)-1]!='\\')
00137                 strcat(transferCallback->outputSubdir, "/");
00138         transferCallback->onFileCallback=onFileCallback;
00139 
00140         // Setup the transfer plugin to get the response to this download request
00141         unsigned short setId = fileListTransfer->SetupReceive(transferCallback, true, host);
00142 
00143         // Send to the host, telling it to process this request
00144         RakNet::BitStream outBitstream;
00145         outBitstream.Write((MessageID)ID_DDT_DOWNLOAD_REQUEST);
00146         outBitstream.Write(setId);
00147         stringCompressor->EncodeString(subdir, 256, &outBitstream);
00148         stringCompressor->EncodeString(outputSubdir, 256, &outBitstream);
00149     localFiles.Serialize(&outBitstream);
00150         SendUnified(&outBitstream, _priority, RELIABLE_ORDERED, _orderingChannel, host, false);
00151 
00152         return setId;
00153 }
00154 void DirectoryDeltaTransfer::ClearUploads(void)
00155 {
00156         availableUploads->Clear();
00157 }
00158 void DirectoryDeltaTransfer::OnDownloadRequest(Packet *packet)
00159 {
00160         char subdir[256];
00161         char remoteSubdir[256];
00162         RakNet::BitStream inBitstream(packet->data, packet->length, false);
00163         FileList remoteFileHash;
00164         FileList delta;
00165         unsigned short setId;
00166     inBitstream.IgnoreBits(8);
00167         inBitstream.Read(setId);
00168         stringCompressor->DecodeString(subdir, 256, &inBitstream);
00169         stringCompressor->DecodeString(remoteSubdir, 256, &inBitstream);
00170         if (remoteFileHash.Deserialize(&inBitstream)==false)
00171         {
00172 #ifdef _DEBUG
00173                 RakAssert(0);
00174 #endif
00175                 return;
00176         }
00177 
00178         availableUploads->GetDeltaToCurrent(&remoteFileHash, &delta, subdir, remoteSubdir);
00179         if (incrementalReadInterface==0)
00180                 delta.PopulateDataFromDisk(applicationDirectory, true, false, true);
00181         else
00182                 delta.FlagFilesAsReferences();
00183 
00184         // This will call the ddtCallback interface that was passed to FileListTransfer::SetupReceive on the remote system
00185         fileListTransfer->Send(&delta, rakPeerInterface, packet->systemAddress, setId, priority, orderingChannel, compressOutgoingSends, incrementalReadInterface, chunkSize);
00186 }
00187 PluginReceiveResult DirectoryDeltaTransfer::OnReceive(Packet *packet)
00188 {
00189         switch (packet->data[0]) 
00190         {
00191         case ID_DDT_DOWNLOAD_REQUEST:
00192                 OnDownloadRequest(packet);
00193                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00194         }
00195 
00196         return RR_CONTINUE_PROCESSING;
00197 }
00198 
00199 unsigned DirectoryDeltaTransfer::GetNumberOfFilesForUpload(void) const
00200 {
00201         return availableUploads->fileList.Size();
00202 }
00203 void DirectoryDeltaTransfer::SetCompressOutgoingSends(bool compress)
00204 {
00205         compressOutgoingSends=compress;
00206 }
00207 
00208 void DirectoryDeltaTransfer::SetDownloadRequestIncrementalReadInterface(IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize)
00209 {
00210         incrementalReadInterface=_incrementalReadInterface;
00211         chunkSize=_chunkSize;
00212 }
00213 
00214 #ifdef _MSC_VER
00215 #pragma warning( pop )
00216 #endif
00217 
00218 #endif // _RAKNET_SUPPORT_*

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