コード例 #1
0
ファイル: SharedFile.cs プロジェクト: thaolt/BitChatClient
            public override bool Equals(object obj)
            {
                if (base.Equals(obj))
                {
                    return(true);
                }

                FileBlockDownloadManager o = obj as FileBlockDownloadManager;

                if (o == null)
                {
                    return(false);
                }

                return(o._blockNumber == this._blockNumber);
            }
コード例 #2
0
ファイル: SharedFile.cs プロジェクト: thaolt/BitChatClient
        private bool WriteBlock(FileBlockDownloadManager downloadedBlock)
        {
            int blockNumber = downloadedBlock.BlockNumber;

            lock (_blockAvailable)
            {
                if (_blockAvailable[blockNumber] == FileBlockState.Available)
                {
                    return(true);
                }

                byte[] blockData    = downloadedBlock.BlockData;
                byte[] actualHash   = _metaData.BlockHash[blockNumber];
                byte[] computedHash = _metaData.ComputeBlockHash(blockData);

                for (int i = 0; i < actualHash.Length; i++)
                {
                    if (actualHash[i] != computedHash[i])
                    {
                        return(false);
                    }
                }

                lock (_fileStream)
                {
                    _fileStream.Position = blockNumber * _metaData.BlockSize;
                    _fileStream.Write(blockData, 0, blockData.Length);
                }

                _blockAvailable[blockNumber] = FileBlockState.Available;
                _availableBlocksCount++;
            }

            Interlocked.Add(ref _bytesDownloadedLastSecond, downloadedBlock.BlockData.Length); //add bytes downloaded for transfer speed calc

            return(true);
        }
コード例 #3
0
ファイル: SharedFile.cs プロジェクト: thaolt/BitChatClient
        private void OnBlockDownloaded(FileBlockDownloadManager downloadedBlock)
        {
            lock (_downloadingBlocks)
            {
                if (_downloadingBlocks.Remove(downloadedBlock))
                {
                    if (WriteBlock(downloadedBlock))
                    {
                        //block downloaded
                        //Debug.Write("SharedFile.BlockDownloaded", "block: " + downloadedBlock.BlockNumber);

                        if (BlockDownloaded != null)
                        {
                            RaiseEventBlockDownloaded();
                        }
                    }
                    else
                    {
                        //block download fail/corrupt; add block again in pending list
                        lock (_pendingBlocks)
                        {
                            _pendingBlocks.Add(downloadedBlock.BlockNumber);
                        }
                    }

                    //start new block download
                    FileBlockDownloadManager newDownload = GetRandomDownloadBlock();
                    if (newDownload != null)
                    {
                        _downloadingBlocks.Add(newDownload);
                    }

                    if (_downloadingBlocks.Count == 0)
                    {
                        //download COMPLETED!

                        //set variables
                        _isComplete           = true;
                        _state                = SharedFileState.Sharing;
                        _availableBlocksCount = _blockAvailable.Length;

                        //stop download monitor
                        _downloadMonitor.Dispose();
                        _downloadMonitor = null;

                        //rename and open file again in read shared mode
                        string filePath = _fileStream.Name;

                        _fileStream.Close();
                        File.SetLastWriteTimeUtc(filePath, _metaData.LastModified);

                        string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath));
                        File.Move(filePath, newFilePath);

                        _fileStream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);

                        //remove seeders
                        lock (_seeders)
                        {
                            _seeders.Clear();
                        }

                        //announce advertisement for the complete file to all chats available with same file
                        SendFileAdvertisement();

                        //notify event to UI
                        //Debug.Write("SharedFile.BlockDownloaded", "COMPLETED!");

                        if (FileDownloaded != null)
                        {
                            RaiseEventFileDownloaded();
                        }
                    }
                }
            }
        }
コード例 #4
0
ファイル: SharedFile.cs プロジェクト: thaolt/BitChatClient
        private void DownloadMonitorAsync(object state)
        {
            try
            {
                if (_state == SharedFileState.Paused)
                {
                    _downloadMonitor = null;
                    return;
                }

                lock (_downloadingBlocks)
                {
                    bool addAnotherBlockForDownload = false;

                    List <FileBlockDownloadManager> inactiveDownloadBlocks = new List <FileBlockDownloadManager>();

                    foreach (FileBlockDownloadManager download in _downloadingBlocks)
                    {
                        if ((DateTime.UtcNow - download.LastResponse).TotalSeconds > DOWNLOAD_INACTIVE_INTERVAL_SECONDS)
                        {
                            //Debug.Write("SharedFile.DownloadMonitorAsync", "InactiveBlock: " + download.BlockNumber);

                            if (!download.IsDownloadPeerSet())
                            {
                                //add to inactive list
                                inactiveDownloadBlocks.Add(download);

                                //add another random block if available to mitigate case when all current blocks peer are not responding
                                addAnotherBlockForDownload = true;
                            }

                            //remove current peer as he is not responding and set last response time
                            download.SetDownloadPeer(null);

                            //re-announce block requirement
                            AnnounceBlockWanted(download.BlockNumber);
                        }
                    }

                    //add another random block if available to mitigate case when all current blocks peer are not responding
                    //this will allow downloading other data blocks from other peers when current block peers not responding
                    if (addAnotherBlockForDownload)
                    {
                        FileBlockDownloadManager download = GetRandomDownloadBlock();

                        if (download != null)
                        {
                            _downloadingBlocks.Add(download);
                        }
                    }

                    //remove extra inactive blocks to maintain total x 2 numbe of blocks
                    //this will prevent memory getting filled with large number of inactive blocks

                    if (_downloadingBlocks.Count > TOTAL_DOWNLOAD_BLOCKS * 2)
                    {
                        foreach (FileBlockDownloadManager downloadBlock in inactiveDownloadBlocks)
                        {
                            _downloadingBlocks.Remove(downloadBlock);

                            if (_downloadingBlocks.Count <= TOTAL_DOWNLOAD_BLOCKS * 2)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            catch (ThreadAbortException)
            {
                _downloadMonitor = null;
            }
            catch (Exception ex)
            {
                Debug.Write("SharedFile.DownloadMonitorAsync", ex);
            }
            finally
            {
                if (_downloadMonitor != null)
                {
                    _downloadMonitor.Change(DOWNLOAD_MONITOR_INTERVAL, Timeout.Infinite);
                }
            }
        }
コード例 #5
0
ファイル: SharedFile.cs プロジェクト: thaolt/BitChatClient
        private void StartDownload()
        {
            if (_state != SharedFileState.Downloading)
            {
                _state = SharedFileState.Downloading;

                //get file
                if (_fileStream == null)
                {
                    //find file name
                    string filePath = Path.Combine(_profile.DownloadFolder, _metaData.FileName);

                    int nameCount = 0;

                    while (File.Exists(filePath))
                    {
                        if (nameCount > 10000)
                        {
                            throw new BitChatException("Cannot download file as local file name not available.");
                        }

                        nameCount++;
                        filePath = Path.Combine(_profile.DownloadFolder, Path.GetFileNameWithoutExtension(_metaData.FileName) + " [" + nameCount + "]" + Path.GetExtension(_metaData.FileName));
                    }

                    //create file
                    _fileStream = new FileStream(filePath + ".downloading", FileMode.Create, FileAccess.ReadWrite);

                    //pre-allocate file
                    _fileStream.SetLength(_metaData.FileSize);

                    //init block available
                    _blockAvailable       = new FileBlockState[_blockAvailable.Length];
                    _availableBlocksCount = 0;
                }

                //list all pending blocks
                if (_pendingBlocks == null)
                {
                    _pendingBlocks   = new List <int>(_blockAvailable.Length);
                    _rndPendingBlock = new Random(DateTime.UtcNow.Second);

                    for (int i = 0; i < _blockAvailable.Length; i++)
                    {
                        if (_blockAvailable[i] != FileBlockState.Available)
                        {
                            _pendingBlocks.Add(i);
                        }
                    }
                }

                //announce file sharing participation in chats
                SendFileShareParticipate();

                //start block download
                _downloadingBlocks = new List <FileBlockDownloadManager>(TOTAL_DOWNLOAD_BLOCKS);

                lock (_downloadingBlocks)
                {
                    for (int i = 0; i < TOTAL_DOWNLOAD_BLOCKS; i++)
                    {
                        FileBlockDownloadManager download = GetRandomDownloadBlock();

                        if (download == null)
                        {
                            break;
                        }

                        _downloadingBlocks.Add(download);
                    }
                }

                //start file transfer speed calculator
                _fileTransferSpeedCalculator = new Timer(FileTransferSpeedCalculatorAsync, null, 1000, 1000);

                //start download monitor
                _downloadMonitor = new Timer(DownloadMonitorAsync, null, DOWNLOAD_MONITOR_INTERVAL, Timeout.Infinite);

                if (FileDownloadStarted != null)
                {
                    RaiseEventFileDownloadStarted();
                }
            }
        }
コード例 #6
0
        private void OnBlockDownloaded(FileBlockDownloadManager downloadedBlock)
        {
            lock (_downloadingBlocks)
            {
                if (_downloadingBlocks.Remove(downloadedBlock))
                {
                    if (WriteBlock(downloadedBlock))
                    {
                        //block downloaded
                        //Debug.Write("SharedFile.BlockDownloaded", "block: " + downloadedBlock.BlockNumber);

                        if (BlockDownloaded != null)
                            RaiseEventBlockDownloaded();
                    }
                    else
                    {
                        //block download fail/corrupt; add block again in pending list
                        lock (_pendingBlocks)
                        {
                            _pendingBlocks.Add(downloadedBlock.BlockNumber);
                        }
                    }

                    //start new block download
                    FileBlockDownloadManager newDownload = GetRandomDownloadBlock();
                    if (newDownload != null)
                        _downloadingBlocks.Add(newDownload);

                    if (_downloadingBlocks.Count == 0)
                    {
                        //download COMPLETED!

                        //set variables
                        _isComplete = true;
                        _state = SharedFileState.Sharing;
                        _availableBlocksCount = _blockAvailable.Length;

                        //stop download monitor
                        _downloadMonitor.Dispose();
                        _downloadMonitor = null;

                        //rename and open file again in read shared mode
                        string filePath = _fileStream.Name;

                        _fileStream.Close();
                        File.SetLastWriteTimeUtc(filePath, _metaData.LastModified);

                        string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath));
                        File.Move(filePath, newFilePath);

                        _fileStream = new FileStream(newFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);

                        //remove seeders
                        lock (_seeders)
                        {
                            _seeders.Clear();
                        }

                        //announce advertisement for the complete file to all chats available with same file
                        SendFileAdvertisement();

                        //notify event to UI
                        //Debug.Write("SharedFile.BlockDownloaded", "COMPLETED!");

                        if (FileDownloaded != null)
                            RaiseEventFileDownloaded();
                    }
                }
            }
        }
コード例 #7
0
        private bool WriteBlock(FileBlockDownloadManager downloadedBlock)
        {
            int blockNumber = downloadedBlock.BlockNumber;

            lock (_blockAvailable)
            {
                if (_blockAvailable[blockNumber] == FileBlockState.Available)
                    return true;

                byte[] blockData = downloadedBlock.BlockData;
                byte[] actualHash = _metaData.BlockHash[blockNumber];
                byte[] computedHash = _metaData.ComputeBlockHash(blockData);

                for (int i = 0; i < actualHash.Length; i++)
                {
                    if (actualHash[i] != computedHash[i])
                        return false;
                }

                lock (_fileStream)
                {
                    _fileStream.Position = blockNumber * _metaData.BlockSize;
                    _fileStream.Write(blockData, 0, blockData.Length);
                }

                _blockAvailable[blockNumber] = FileBlockState.Available;
                _availableBlocksCount++;
            }

            Interlocked.Add(ref _bytesDownloadedLastSecond, downloadedBlock.BlockData.Length); //add bytes downloaded for transfer speed calc

            return true;
        }