Пример #1
0
 /// <summary>
 /// Registers the task in the storage.
 /// </summary>
 /// <param name="task">The DownloadTask instance.</param>
 public void RegisterTask(DownloadTask task)
 {
     lock (registry)
     {
         if (!TasksDictionary.ContainsKey(task.DownloadItem.Enclosure.Url))
         {
             TasksDictionary.Add(task.DownloadItem.Enclosure.Url, task);
             AddTask(task);
         }
         else //change state to downloading because we are reattempting
         {
             TasksDictionary[task.DownloadItem.Enclosure.Url].State = DownloadTaskState.Pending;
         }
     }
     SaveTask(task);
 }
Пример #2
0
        /// <summary>
        /// Load the tasks stored in a specified path.
        /// </summary>
        /// <param name="taskFilePath">The base path for the registry storage.</param>
        /// <returns>An DownloadTask instance.</returns>
        private DownloadTask LoadTask(string taskFilePath)
        {
            DownloadTask task      = null;
            var          formatter = new BinaryFormatter();

            using (var stream = new FileStream(taskFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                try
                {
                    task            = (DownloadTask)formatter.Deserialize(stream);
                    task.Downloader = (task.SupportsBITS ? (IDownloader)bitsDownloader : (IDownloader)httpDownloader);

                    lock (registry)
                    {
                        //TODO: Once we have a UI for managing enclosures we'll need to
                        //always load all tasks.
                        if (!registry.ContainsKey(task.DownloadItem.Enclosure.Url))
                        {
                            // Revert to pending if it was in a downloading state
                            if (task.State == DownloadTaskState.Downloading)
                            {
                                task.State = DownloadTaskState.Pending;
                            }

                            registry.Add(task.DownloadItem.Enclosure.Url, task);
                            AddTask(task);
                        }
                        else
                        {
                            string fileName = Path.Combine(RootDir.FullName, task.TaskId + ".task");
                            // it might be currrently opened:
                            if (String.Equals(taskFilePath, fileName, StringComparison.OrdinalIgnoreCase))
                            {
                                stream.Close();
                            }
                            FileHelper.DestroyFile(fileName);
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.Error("Error in DownloadRegistryManager.LoadTask():", e);
                }
            }
            return(task);
        }
Пример #3
0
        /// <summary>
        /// Removes the task from the storage.
        /// </summary>
        /// <param name="task">The DownloadTask.</param>
        public void UnRegisterTask(DownloadTask task)
        {
            lock (registry)
            {
                if (TasksDictionary.ContainsKey(task.DownloadItem.Enclosure.Url))
                {
                    TasksDictionary.Remove(task.DownloadItem.Enclosure.Url);
                    RemoveTask(task);
                    var disposable = task.Downloader as IDisposable;
                    if (disposable != null)
                    {
                        disposable.Dispose();
                    }
                }
            }
            string fileName = Path.Combine(RootDir.FullName, task.TaskId + ".task");

            FileHelper.DestroyFile(fileName);
        }
Пример #4
0
        /// <summary>
        /// Synchronous download method implementation.
        /// </summary>
        /// <param name="task">The DownloadTask to process.</param>
        /// <param name="maxWaitTime">The maximum wait time.</param>
        public void Download(DownloadTask task, TimeSpan maxWaitTime)
        {
            currentTask = task;

            // If we resume way too often, just return
            if (CheckForResumeAndProceed(currentTask))
            {
                return;
            }

            WebResponse response = SyncWebRequest.GetResponse(HttpMethod.Get, task.DownloadItem.Enclosure.Url,
                                                              task.DownloadItem.Credentials,
                                                              FeedSource.UserAgentString(String.Empty),
                                                              task.DownloadItem.Proxy,
                                                              DateTime.MinValue,
                                                              null /* eTag */,
                                                              Convert.ToInt32(maxWaitTime.TotalSeconds),
                                                              null /* cookie */, null /* body */, null /* newsGatorAPIToken */);

            OnRequestComplete(new Uri(task.DownloadItem.Enclosure.Url), response.GetResponseStream(), response, null, null,
                              DateTime.MinValue, RequestResult.OK, 0);
        }
Пример #5
0
        /// <summary>
        /// Cancels an asynhronous download operation.
        /// </summary>
        /// <param name="task">The <see cref="DownloadTask"/> for the operation.</param>
        /// <returns>Indicates whether the operation was canceled.</returns>
        public bool CancelDownload(DownloadTask task)
        {
            IBackgroundCopyManager copyManager = null;
            IBackgroundCopyJob     pJob        = null;

            if (task.JobId != null)
            {
                try
                {
                    Guid jobID = task.JobId.Value;
                    copyManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                    copyManager.GetJob(ref jobID, out pJob);

                    if (pJob != null)
                    {
                        pJob.Cancel();
                    }
                }
                catch (COMException)
                {
                    /* we may come up empty when trying to get the job */
                }
                finally
                {
                    if (copyManager != null)
                    {
                        Marshal.ReleaseComObject(copyManager);
                    }

                    if (pJob != null)
                    {
                        Marshal.ReleaseComObject(pJob);
                    }
                }
            }
            return(true);
        }
Пример #6
0
        /// <summary>
        /// Stores a task in the registry storage.
        /// </summary>
        /// <param name="task">The DownloadTask instance.</param>
        private void SaveTask(DownloadTask task)
        {
            string filename = Path.Combine(RootDir.FullName,
                                           String.Format(CultureInfo.InvariantCulture, "{0}.task", task.TaskId));

            try
            {
                using (Stream stream = FileHelper.OpenForWrite(filename))
                {
                    var formatter = new BinaryFormatter();
                    formatter.Serialize(stream, task);
                }
            }
            catch (IOException ex)
            {
                Logger.Error(ex);
            }
            catch (Exception ex)
            {
                File.Delete(filename);
                Logger.Error(ex);
                throw;
            }
        }
Пример #7
0
 /// <summary>
 /// Method called by BITS when the job is completed.
 /// </summary>
 /// <param name="task">The Updater task instance.</param>
 /// <param name="pJob">The BITS job reeference.</param>
 private void OnJobTransferred(DownloadTask task, IBackgroundCopyJob pJob)
 {
     pJob.Complete();
     OnDownloadCompleted(new TaskEventArgs(task));
 }
Пример #8
0
        /// <summary>
        /// Method responsible for checking the authentication type and setting the
        /// appropriate credentials. If the NTLM authentication is used then
        /// if the username and password are not provided then we use null values. For
        /// all other authentication schemes we need a username and password.
        /// </summary>
        /// <param name="backgroundCopyJob">BackgroundJob on which we need to set the credentials.</param>
        /// <param name="task">DownloadTask. Provides the infos about download credentials</param>
        private static void VerifyAndSetBackgroundCopyJobCredentials(IBackgroundCopyJob backgroundCopyJob, DownloadTask task)
        {
            try
            {
                var          copyJob = (IBackgroundCopyJob2)backgroundCopyJob;
                ICredentials creds   = task.DownloadItem.Credentials;
                var          uri     = new Uri(task.DownloadItem.File.Source);

                if (creds != null)
                {
                    //Specify HTTP Authentication (Basic) credentials
                    var credentials = new BG_AUTH_CREDENTIALS();
                    credentials.Credentials.Basic.UserName = creds.GetCredential(uri, "Basic").UserName;
                    credentials.Credentials.Basic.Password = creds.GetCredential(uri, "Basic").Password;
                    credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_BASIC;
                    credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_SERVER;
                    copyJob.SetCredentials(ref credentials);

                    //Specify HTTP Authentication (Digest) credentials
                    credentials = new BG_AUTH_CREDENTIALS();
                    credentials.Credentials.Basic.UserName = creds.GetCredential(uri, "Digest").UserName;
                    credentials.Credentials.Basic.Password = creds.GetCredential(uri, "Digest").Password;
                    credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_DIGEST;
                    credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_SERVER;
                    copyJob.SetCredentials(ref credentials);

                    //Specify NTLM credentials
                    credentials = new BG_AUTH_CREDENTIALS();
                    credentials.Credentials.Basic.UserName =
                        string.IsNullOrEmpty(creds.GetCredential(uri, "NTLM").Domain)
                            ?
                        creds.GetCredential(uri, "NTLM").UserName
                            :
                        creds.GetCredential(uri, "NTLM").Domain + "\\" +
                        creds.GetCredential(uri, "NTLM").UserName;
                    credentials.Credentials.Basic.Password = creds.GetCredential(uri, "NTLM").Password;
                    credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_NTLM;
                    credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_SERVER;
                    copyJob.SetCredentials(ref credentials);
                } //if(creds != null)
            }
            catch (Exception e)
            {
                Logger.Error("Error in VerifyAndSetBackgroundCopyJobCredentials():", e);
            }
        }
Пример #9
0
        /// <summary>
        /// Method responsible for checking the proxy and proxy authentication type and setting the
        /// appropriate credentials. If the NTLM authentication is used then
        /// if the username and password are not provided then we use null values. For
        /// all other authentication schemes we need a username and password.
        /// </summary>
        /// <param name="backgroundCopyJob">BackgroundJob on which we need to set the credentials.</param>
        /// <param name="task">DownloadTask. Provides the infos about download credentials</param>
        private static void VerifyAndSetBackgroundCopyJobProxy(IBackgroundCopyJob backgroundCopyJob, DownloadTask task)
        {
            // Specify the proxy URL
            // see also http://msdn.microsoft.com/library/en-us/bits/bits/ibackgroundcopyjob_setproxysettings.asp
            try
            {
                IWebProxy proxy     = task.DownloadItem.Proxy;
                var       sourceUri = new Uri(task.DownloadItem.File.Source);
                Uri       proxyUri  = proxy.GetProxy(sourceUri);
                //trim trailing '/' because it causes BITS to throw an exception
                string proxyUriStr = proxyUri.ToString().TrimEnd('/');

                if (!proxy.IsBypassed(proxyUri))
                {
                    backgroundCopyJob.SetProxySettings(BG_JOB_PROXY_USAGE.BG_JOB_PROXY_USAGE_OVERRIDE, proxyUriStr, null);
                }

                //specify proxy credentials
                if (proxy.Credentials != null)
                {
                    ICredentials creds   = proxy.Credentials;
                    var          copyJob = (IBackgroundCopyJob2)backgroundCopyJob;

                    var credentials = new BG_AUTH_CREDENTIALS();
                    credentials.Credentials.Basic.UserName =
                        string.IsNullOrEmpty(creds.GetCredential(sourceUri, "NTLM").Domain)
                            ?
                        creds.GetCredential(sourceUri, "NTLM").UserName
                            :
                        creds.GetCredential(sourceUri, "NTLM").Domain + "\\" +
                        creds.GetCredential(sourceUri, "NTLM").UserName;
                    credentials.Credentials.Basic.Password = creds.GetCredential(sourceUri, "NTLM").Password;
                    credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_NTLM;
                    credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_PROXY;
                    copyJob.SetCredentials(ref credentials);
                }
            }
            catch (Exception e)
            {
                Logger.Error("Error in VerifyAndSetBackgroundCopyJobProxy():", e);
            }
        }
Пример #10
0
        /// <summary>
        /// Waits for the download to complete, for the synchronous usage of the downloader.
        /// </summary>
        /// <param name="backgroundCopyJob">The job instance reference.</param>
        /// <param name="maxWaitTime">The maximum wait time.</param>
        /// <param name="task">The updater task instance.</param>
        private void WaitForDownload(DownloadTask task, IBackgroundCopyJob backgroundCopyJob, TimeSpan maxWaitTime)
        {
            bool isCompleted  = false;
            bool isSuccessful = false;

            try
            {
                Guid jobID;
                backgroundCopyJob.GetId(out jobID);

                //  set endtime to current tickcount + allowable # milliseconds to wait for job
                double endTime = Environment.TickCount + maxWaitTime.TotalMilliseconds;

                while (!isCompleted)
                {
                    BG_JOB_STATE state;
                    backgroundCopyJob.GetState(out state);
                    switch (state)
                    {
                    case BG_JOB_STATE.BG_JOB_STATE_SUSPENDED:
                    {
                        OnDownloadStarted(new TaskEventArgs(task));
                        backgroundCopyJob.Resume();
                        break;
                    }

                    case BG_JOB_STATE.BG_JOB_STATE_ERROR:
                    {
                        //  use utility to:
                        //  a)  get error info
                        //  b)  report it
                        //  c)  cancel and remove copy job
                        OnJobError(task, backgroundCopyJob, null, null);

                        //  complete loop, but DON'T say it's successful
                        isCompleted = true;
                        break;
                    }

                    case BG_JOB_STATE.BG_JOB_STATE_TRANSIENT_ERROR:
                    {
                        //  NOTE:  during debugging + test, transient errors resulted in complete job failure about 90%
                        //  of the time.  Therefore we treat transients just like full errors, and CANCEL the job
                        //  use utility to manage error etc.
                        OnJobError(task, backgroundCopyJob, null, null);

                        //  stop the loop, set completed to true but not successful
                        isCompleted = true;
                        break;
                    }

                    case BG_JOB_STATE.BG_JOB_STATE_TRANSFERRING:
                    {
                        OnJobModification(task, backgroundCopyJob);
                        break;
                    }

                    case BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED:
                    {
                        OnJobTransferred(task, backgroundCopyJob);

                        isCompleted  = true;
                        isSuccessful = true;
                        break;
                    }

                    default:
                        break;
                    }

                    if (isCompleted)
                    {
                        break;
                    }

                    if (endTime < Environment.TickCount)
                    {
                        var ex = new DownloaderException("Download attempt timed out");
                        OnJobError(task, backgroundCopyJob, null, ex);
                        break;
                    }

                    //  Avoid 100% CPU utilisation with too tight a loop, let download happen.
                    Thread.Sleep(TimeToWaitDuringSynchronousDownload);
                }

                if (!isSuccessful)
                {
                    //  create message + error, package it, publish
                    var ex =
                        new DownloaderException(String.Format("Download attempt for {0} failed",
                                                              task.DownloadItem.ItemId));
                    OnJobError(task, backgroundCopyJob, null, ex);
                }
            }
            catch (ThreadInterruptedException tie)
            {
                //  if interrupted, clean up job
                OnJobError(task, backgroundCopyJob, null, tie);
            }
        }
Пример #11
0
        /// <summary>
        /// Asynchronous download method implementation.
        /// </summary>
        /// <param name="task">The DownloadTask to process.</param>
        public void BeginDownload(DownloadTask task)
        {
            IBackgroundCopyManager backGroundCopyManager = null;
            IBackgroundCopyJob     backgroundCopyJob     = null;
            Guid jobID = Guid.Empty;

            try
            {
                //  create the manager
                backGroundCopyManager = (IBackgroundCopyManager) new BackgroundCopyManager();

                // If the job is already finished, just return
                if (CheckForResumeAndProceed(backGroundCopyManager, task, out backgroundCopyJob))
                {
                    return;
                }

                if (backgroundCopyJob != null)
                {
                    // if CheckForResumeAndProceed connected to an ongoing BITS job
                    // wire up our notify interface to forward events to the client

                    backgroundCopyJob.SetNotifyInterface(this);

                    backgroundCopyJob.SetNotifyFlags((uint)(
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_ERROR |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_MODIFICATION |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_TRANSFERRED)
                                                     );
                }
                else
                {
                    //  use utility function to create the job.
                    CreateCopyJob(
                        backGroundCopyManager,
                        out backgroundCopyJob,
                        ref jobID,
                        task.DownloadItem.OwnerItemId,
                        task.DownloadItem.Enclosure.Description, task);

                    // Save the jobId in the task
                    task.JobId = jobID;

                    // Prepare the job to download the manifest files
                    PrepareJob(backgroundCopyJob, task);

                    // Set the notify interface to get BITS events
                    backgroundCopyJob.SetNotifyInterface(this);

                    backgroundCopyJob.SetNotifyFlags((uint)(
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_ERROR |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_MODIFICATION |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_TRANSFERRED)
                                                     );

                    // Fire our download start event
                    OnDownloadStarted(new TaskEventArgs(task));

                    // Initiate the BITS Job
                    backgroundCopyJob.Resume();
                }
            }
            catch (Exception e)
            {
                //  if exception, clean up job
                OnJobError(task, backgroundCopyJob, null, e);
            }
            finally
            {
                if (null != backgroundCopyJob)
                {
                    Marshal.ReleaseComObject(backgroundCopyJob);
                }
                if (null != backGroundCopyManager)
                {
                    Marshal.ReleaseComObject(backGroundCopyManager);
                }
            }
        }
Пример #12
0
 private void RemoveTask(DownloadTask task)
 {
     _context.Post(o => _tasks.Remove(task), null);
 }
Пример #13
0
 private void AddTask(DownloadTask task)
 {
     _context.Post(o => _tasks.Add(task), null);
 }
Пример #14
0
 /// <summary>
 /// Updates the information of an existing stored task.
 /// </summary>
 /// <param name="task">The DownloadTask instance.</param>
 public void UpdateTask(DownloadTask task)
 {
     SaveTask(task);
 }
Пример #15
0
 /// <summary>
 /// Constructor for a TaskEventArgs.
 /// </summary>
 /// <param name="task">The DownloadTask for initialization.</param>
 public TaskEventArgs(DownloadTask task)
 {
     currentDownloadTask = task;
 }
Пример #16
0
 /// <summary>
 /// Constructor for the DownloadTaskErrorEventArgs.
 /// </summary>
 /// <param name="task">The <see cref="DownloadTask"/> instance.</param>
 /// <param name="exception">The exception information.</param>
 public DownloadTaskErrorEventArgs(DownloadTask task, Exception exception) : base(task)
 {
     this.exception = exception;
 }