public SharedFileInfo(string filePath, SharedFileMetaData fileMetaData, FileBlockState[] blockAvailable, bool isPaused) { _filePath = filePath; _fileMetaData = fileMetaData; _blockAvailable = blockAvailable; _isPaused = isPaused; }
internal static SharedFile ShareFile(string filePath, string hashAlgo, BitChat chat, SynchronizationContext syncCxt) { FileStream fS = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); HashAlgorithm hash = HashAlgorithm.Create(hashAlgo); int hashSize = hash.HashSize / 8; //calculate block size int blockSize; { //header size = ChatMessage header + FileAdvertisement header int packetHeaderSize = (20 + 1 + 2) + (1 + 1 + 255 + 1 + 255 + 8 + 8 + 4 + 1 + 10 + 1); int packetDataSize = 65536 - packetHeaderSize; int totalBlocksPossible = packetDataSize / hashSize; blockSize = Convert.ToInt32(fS.Length / totalBlocksPossible); if (blockSize <= short.MaxValue) { blockSize = short.MaxValue + 1; } else { //align to 16 bytes int remainder = blockSize % 16; if (remainder > 0) { blockSize = blockSize - remainder + 16; } } } //compute block hashes and file info hash int totalBlocks = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((double)fS.Length / blockSize))); byte[][] blockHash = new byte[totalBlocks][]; FileBlockState[] blockAvailable = new FileBlockState[totalBlocks]; //init for (int i = 0; i < totalBlocks; i++) { long offset = i * blockSize; long length = blockSize; if ((offset + length) > fS.Length) { length = fS.Length - offset; } blockHash[i] = hash.ComputeHash(new OffsetStream(fS, offset, length)); blockAvailable[i] = FileBlockState.Available; } //get file meta data SharedFileMetaData metaData = new SharedFileMetaData(Path.GetFileName(fS.Name), WebUtilities.GetContentType(fS.Name), File.GetLastWriteTimeUtc(fS.Name), fS.Length, blockSize, hashAlgo, blockHash); //check if file already shared lock (_sharedFiles) { SharedFile sharedFile; if (_sharedFiles.ContainsKey(metaData.FileID)) { sharedFile = _sharedFiles[metaData.FileID]; if (sharedFile._isComplete) { fS.Dispose(); } else { sharedFile.Remove(chat); sharedFile = new SharedFile(fS, metaData, blockAvailable, blockAvailable.Length, syncCxt); sharedFile.StartSharing(); _sharedFiles.Add(metaData.FileID, sharedFile); } } else { sharedFile = new SharedFile(fS, metaData, blockAvailable, blockAvailable.Length, syncCxt); sharedFile.StartSharing(); _sharedFiles.Add(metaData.FileID, sharedFile); } sharedFile.AddChat(chat); return(sharedFile); } }
internal static SharedFile ShareFile(string filePath, string hashAlgo, BitChat chat, SynchronizationContext syncCxt) { FileStream fS = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); HashAlgorithm hash = HashAlgorithm.Create(hashAlgo); int hashSize = hash.HashSize / 8; //calculate block size int blockSize; { //header size = ChatMessage header + FileAdvertisement header int packetHeaderSize = (20 + 1 + 2) + (1 + 1 + 255 + 1 + 255 + 8 + 8 + 4 + 1 + 10 + 1); int packetDataSize = 65536 - packetHeaderSize; int totalBlocksPossible = packetDataSize / hashSize; blockSize = Convert.ToInt32(fS.Length / totalBlocksPossible); if (blockSize <= short.MaxValue) blockSize = short.MaxValue + 1; else { //align to 16 bytes int remainder = blockSize % 16; if (remainder > 0) blockSize = blockSize - remainder + 16; } } //compute block hashes and file info hash int totalBlocks = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((double)fS.Length / blockSize))); byte[][] blockHash = new byte[totalBlocks][]; FileBlockState[] blockAvailable = new FileBlockState[totalBlocks]; //init for (int i = 0; i < totalBlocks; i++) { long offset = i * blockSize; long length = blockSize; if ((offset + length) > fS.Length) length = fS.Length - offset; blockHash[i] = hash.ComputeHash(new OffsetStream(fS, offset, length)); blockAvailable[i] = FileBlockState.Available; } //get file meta data SharedFileMetaData metaData = new SharedFileMetaData(Path.GetFileName(fS.Name), WebUtilities.GetContentType(fS.Name), File.GetLastWriteTimeUtc(fS.Name), fS.Length, blockSize, hashAlgo, blockHash); //check if file already shared lock (_sharedFiles) { SharedFile sharedFile; if (_sharedFiles.ContainsKey(metaData.FileID)) { sharedFile = _sharedFiles[metaData.FileID]; if (sharedFile._isComplete) { fS.Dispose(); } else { sharedFile.Remove(chat); sharedFile = new SharedFile(fS, metaData, blockAvailable, blockAvailable.Length, syncCxt); sharedFile.StartSharing(); _sharedFiles.Add(metaData.FileID, sharedFile); } } else { sharedFile = new SharedFile(fS, metaData, blockAvailable, blockAvailable.Length, syncCxt); sharedFile.StartSharing(); _sharedFiles.Add(metaData.FileID, sharedFile); } sharedFile.AddChat(chat); return sharedFile; } }
private SharedFile(FileStream fS, SharedFileMetaData metaData, FileBlockState[] blockAvailable, int availableBlocksCount, SynchronizationContext syncCxt) { _fileStream = fS; _metaData = metaData; _blockAvailable = blockAvailable; _availableBlocksCount = availableBlocksCount; _syncCxt = syncCxt; _isComplete = (_blockAvailable.Length == _availableBlocksCount); }
internal static SharedFile LoadFile(string filePath, SharedFileMetaData metaData, FileBlockState[] blockAvailable, bool isPaused, BitChat chat, SynchronizationContext syncCxt) { //check if file already shared lock (_sharedFiles) { SharedFile sharedFile; if (_sharedFiles.ContainsKey(metaData.FileID)) { sharedFile = _sharedFiles[metaData.FileID]; } else { int availableBlocksCount = 0; for (int i = 0; i < blockAvailable.Length; i++) { if (blockAvailable[i] == FileBlockState.Available) availableBlocksCount++; } FileStream fS; if (blockAvailable.Length == availableBlocksCount) fS = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); else fS = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite); sharedFile = new SharedFile(fS, metaData, blockAvailable, availableBlocksCount, syncCxt); sharedFile._state = SharedFileState.Paused; _sharedFiles.Add(metaData.FileID, sharedFile); if (!isPaused) sharedFile.Start(); } sharedFile.AddChat(chat); return sharedFile; } }