internal void AddData(long fileOffset, byte[] fileData, Frame frame) { if (this.initialFrameNumber < 0 || frame.FrameNumber < this.initialFrameNumber) { this.initialFrameNumber = frame.FrameNumber; this.initialTimeStamp = frame.Timestamp; } if (this.fileStream == null) { this.tempFilePath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.cache, this.fiveTuple, this.transferIsClientToServer, FileStreamTypes.SMB2, "", this.FilePath, this.fileStreamAssemblerList, uniqueFileId.GetHashCode().ToString("X4") + "-" + Utils.StringManglerUtil.ConvertToFilename(FilePath, 20)).absolutPath; this.fileStream = new System.IO.FileStream(tempFilePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024);//256 kB buffer is probably a suitable value for good performance on large files } if (this.fileStream != null && this.fileStream.CanWrite) { if (fileStream.Position != fileOffset) { fileStream.Seek(fileOffset, System.IO.SeekOrigin.Begin); } fileStream.Write(fileData, 0, fileData.Length); if (this.segmentOffsetBytesWritten.ContainsKey(fileOffset)) { this.segmentOffsetBytesWritten[fileOffset] = Math.Max(fileData.Length, this.segmentOffsetBytesWritten[fileOffset]); } else { this.segmentOffsetBytesWritten.Add(fileOffset, fileData.Length); } //check if we have 100% of the file long index = 0; foreach (var kvp in this.segmentOffsetBytesWritten) { if (kvp.Key < index) { break; } index = Math.Max(index, kvp.Key + kvp.Value); } if (index > 0 && index == this.fileSize) { this.AssembleAndClose(); } } }
internal ReconstructedFile Reassemble() { string destinationPath = FileStreamAssembler.GetFilePath(this.fileAssmeblyRootLocation, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.fileLocation, this.filename, this.parentAssemblerList, this.extendedFileId); ReconstructedFile reconstructedFile = null; using (System.IO.FileStream fullFileStream = new System.IO.FileStream(destinationPath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024)) {//256 kB buffer is probably a suitable value for good performance on large files foreach (KeyValuePair <long, ReconstructedFile> part in this.filePartList) { //if (fullFileStream.Position != part.Key) // fullFileStream.Seek(part.Key, System.IO.SeekOrigin.Begin); long partOffset = fullFileStream.Position - part.Key; if (partOffset < part.Key + part.Value.FileSize) { using (System.IO.FileStream partStream = new System.IO.FileStream(part.Value.FilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, 256 * 1024)) { if (partOffset > 0) { partStream.Seek(partOffset, System.IO.SeekOrigin.Begin); } //Stream.CopyTo isn't available in .NET 2.0 so I'll have to copy the data manually byte[] buffer = new byte[4096]; int bytesRead = partStream.Read(buffer, 0, buffer.Length); while (bytesRead > 0) { fullFileStream.Write(buffer, 0, bytesRead); bytesRead = partStream.Read(buffer, 0, buffer.Length); } } } } fullFileStream.Close();//so that I can read the full size of the file when creating the ReconstructedFile reconstructedFile = new ReconstructedFile(destinationPath, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.extendedFileId, this.initialFrameNumber, this.timestamp, this.serverHostname); } this.closed = true; this.filePartList.Clear(); return(reconstructedFile); }
internal void AddData(long fileOffset, byte[] fileData, Frame frame) { if (this.initialFrameNumber < 0 || frame.FrameNumber < this.initialFrameNumber) { this.initialFrameNumber = frame.FrameNumber; this.initialTimeStamp = frame.Timestamp; } if (this.fileStream == null) { this.tempFilePath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.cache, this.fiveTuple, this.transferIsClientToServer, FileStreamTypes.SMB2, "", this.filePath, this.fileStreamAssemblerList, uniqueFileId.GetHashCode().ToString("X4") + "-" + Utils.StringManglerUtil.ConvertToFilename(filePath, 20)); this.fileStream = new System.IO.FileStream(tempFilePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None, 256 * 1024);//256 kB buffer is probably a suitable value for good performance on large files } if (this.fileStream != null && this.fileStream.CanWrite) { if (fileStream.Position != fileOffset) { fileStream.Seek(fileOffset, System.IO.SeekOrigin.Begin); } fileStream.Write(fileData, 0, fileData.Length); } }
internal void Close() { //TODO release all file handles and flush data to disk and move file from cache to server/port directory if (this.fileStream != null) { this.fileStream.Close(); } if (this.parentAssemblerList != null) { this.parentAssemblerList.Remove(this.uniqueFileId); } string fixedFilename = this.filePath;//no directory info string fixedFileLocation = ""; FileStreamAssembler.FixFilenameAndLocation(ref fixedFilename, ref fixedFileLocation); string destinationPath; //reassemble the files at the server, regardless if they were downloaded from there or uploaded to the server if (this.transferIsClientToServer) { destinationPath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.destination, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, fixedFileLocation, fixedFilename, this.fileStreamAssemblerList, ""); } else { destinationPath = FileStreamAssembler.GetFilePath(FileStreamAssembler.FileAssmeblyRootLocation.source, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, fixedFileLocation, fixedFilename, this.fileStreamAssemblerList, ""); } //I need to create the directory here since the file might either be moved to this located or a new file will be created there from a stream //string directoryName = destinationPath.Substring(0, destinationPath.Length - fixedFilename.Length); string directoryName = System.IO.Path.GetDirectoryName(destinationPath); if (!System.IO.Directory.Exists(directoryName)) { try { System.IO.Directory.CreateDirectory(directoryName); } catch (Exception e) { this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error creating directory \"" + directoryName + "\" for path \"" + destinationPath + "\".\n" + e.Message); } } //files which are already completed can simply be moved to their final destination if (this.fileStream != null) { this.fileStream.Close(); } try { //string tmpPath = this.tempFilePath; if (System.IO.File.Exists(this.tempFilePath)) { System.IO.File.Move(this.tempFilePath, destinationPath); } } catch (Exception e) { this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error moving file \"" + this.tempFilePath + "\" to \"" + destinationPath + "\". " + e.Message); } if (System.IO.File.Exists(destinationPath)) { try { ReconstructedFile completedFile = new ReconstructedFile(destinationPath, this.fiveTuple, this.transferIsClientToServer, this.fileStreamType, this.details, this.initialFrameNumber, this.initialTimeStamp, this.serverHostname); this.fileStreamAssemblerList.PacketHandler.AddReconstructedFile(completedFile); //parentAssemblerList.PacketHandler.ParentForm.ShowReconstructedFile(completedFile); } catch (Exception e) { this.fileStreamAssemblerList.PacketHandler.OnAnomalyDetected("Error creating reconstructed file: " + e.Message); } } }