internal static SharedFile LoadFile(string filePath, SharedFileMetaData metaData, byte[] blockAvailable, SharedFileState state, SynchronizationContext syncCxt) { //check if file already shared lock (_sharedFiles) { SharedFile sharedFile; if (_sharedFiles.ContainsKey(metaData.FileID)) { sharedFile = _sharedFiles[metaData.FileID]; } else { if (state == SharedFileState.Advertisement) { sharedFile = new SharedFile(null, metaData, new byte[metaData.BlockHash.Length], 0, syncCxt); _sharedFiles.Add(metaData.FileID, sharedFile); sharedFile._state = SharedFileState.Advertisement; } else { int availableBlocksCount = 0; for (int i = 0; i < blockAvailable.Length; i++) { if (blockAvailable[i] == FILE_BLOCK_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); _sharedFiles.Add(metaData.FileID, sharedFile); sharedFile._state = SharedFileState.Paused; if (state != SharedFileState.Paused) { sharedFile.Start(); } } } return(sharedFile); } }
private SharedFile(FileStream fS, SharedFileMetaData metaData, byte[] blockAvailable, int availableBlocksCount, SynchronizationContext syncCxt) { _fileStream = fS; _metaData = metaData; _blockAvailable = blockAvailable; _availableBlocksCount = availableBlocksCount; _syncCxt = syncCxt; _isComplete = (_blockAvailable.Length == _availableBlocksCount); }
internal static SharedFile PrepareDownloadFile(SharedFileMetaData metaData, SynchronizationContext syncCxt) { //check if file already exists lock (_sharedFiles) { SharedFile sharedFile; if (_sharedFiles.ContainsKey(metaData.FileID)) { sharedFile = _sharedFiles[metaData.FileID]; } else { sharedFile = new SharedFile(null, metaData, new byte[metaData.BlockHash.Length], 0, syncCxt); _sharedFiles.Add(metaData.FileID, sharedFile); } return(sharedFile); } }
internal static SharedFile ShareFile(string filePath, string hashAlgo, 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; { int totalBlocksPossible = BUFFER_SIZE / hashSize; blockSize = Convert.ToInt32(fS.Length / totalBlocksPossible); if (blockSize < FILE_BLOCK_MINIMUM_SIZE) { blockSize = FILE_BLOCK_MINIMUM_SIZE; } 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][]; byte[] blockAvailable = new byte[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] = FILE_BLOCK_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) { //close the file and do nothing fS.Dispose(); } else { //since the current shared file is incomplete and we are adding a complete shared file copy //stop current download process sharedFile.Pause(); sharedFile._fileStream.Dispose(); //update the current object with new file data sharedFile._fileStream = fS; sharedFile._blockAvailable = blockAvailable; sharedFile._availableBlocksCount = blockAvailable.Length; sharedFile._isComplete = true; //start sharing new file sharedFile.StartSharing(); } } else { sharedFile = new SharedFile(fS, metaData, blockAvailable, blockAvailable.Length, syncCxt); sharedFile.StartSharing(); _sharedFiles.Add(metaData.FileID, sharedFile); } return(sharedFile); } }