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();
                }
            }
        }
Пример #2
0
        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);
                }
            }
        }