/* * Copyright (C) 2007 Eskil Bylund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ using System; using System.Collections.Generic; using DCSharp.Backend.Managers; using DCSharp.Backend.Objects; using DCSharp.Xml; namespace DCSharp { // TODO: Get whether or not to monitor from the settings. /// /// Finds sources for the active downloads. /// public class FileFinder : IDisposable { private Runtime runtime; private ActionQueue actionQueue; private bool monitorLists; private bool monitorResults; public FileFinder(Runtime runtime) { if (runtime == null) { throw new ArgumentNullException("runtime"); } this.runtime = runtime; actionQueue = new ActionQueue("FileFinderThread"); runtime.DownloadManager.DownloaderAdded += OnDownloaderAdded; runtime.DownloadManager.DownloaderRemoved += OnDownloaderRemoved; runtime.SearchManager.ResultReceived += OnResultReceived; } #region Properties public bool MonitorFileLists { get { return monitorLists; } set { monitorLists = value; } } public bool MonitorSearchResults { get { return monitorResults; } set { monitorResults = value; } } #endregion #region Methods public void CheckFileList(User user) { ListDownloader downloader = runtime.DownloadManager.Find( delegate(ListDownloader ld) { return ld.User == user; }); if (downloader == null && !actionQueue.Contains(user)) { Monitor(runtime.DownloadManager.DownloadList(user)); } } public void Dispose() { runtime.DownloadManager.DownloaderAdded -= OnDownloaderAdded; runtime.DownloadManager.DownloaderRemoved -= OnDownloaderRemoved; runtime.SearchManager.ResultReceived -= OnResultReceived; } #region Search private void OnResultReceived(object obj, ResultReceivedEventArgs args) { SearchResult result = args.Result; if (monitorResults && result.TTH != null) { FileDownloader downloader = runtime.DownloadManager.GetDownloader(result.TTH) as FileDownloader; if (downloader != null) { downloader.AddSource(result.User); } } } #endregion #region FileList private void Monitor(ListDownloader downloader) { downloader.ListReceived += OnListReceived; } private void OnDownloaderAdded(object obj, DownloadEventArgs args) { ListDownloader downloader = args.Downloader as ListDownloader; if (monitorLists && downloader != null) { Monitor(downloader); } } private void OnDownloaderRemoved(object obj, DownloadEventArgs args) { ListDownloader downloader = args.Downloader as ListDownloader; if (downloader != null) { downloader.ListReceived -= OnListReceived; } } private void OnListReceived(object obj, EventArgs args) { ListDownloader downloader = (ListDownloader)obj; if (downloader.Result != null) { actionQueue.Queue(downloader.User, FindSources, downloader); } } private void FindSources(object state) { ListDownloader downloader = (ListDownloader)state; FindSources(downloader.Result, downloader.User); } private void FindSources(FileList list, User user) { Queue queue = new Queue(list.Directories); while (queue.Count > 0) { DirectoryNode directory = queue.Dequeue(); foreach (DirectoryNode child in directory.Directories) { queue.Enqueue(child); } foreach (FileNode file in directory.Files) { if (file.TTH != null) { FileDownloader downloader = runtime.DownloadManager.GetDownloader(file.TTH) as FileDownloader; if (downloader != null) { downloader.AddSource(user); } } } } } #endregion #endregion } }