Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  lib.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! An interface for managing and monitoring BITS jobs.
//!
//! BITS is a Windows service for performing downloads in the background, independent from an
//! application, usually via HTTP/HTTPS.
//!
//! [`BitsClient`](enum.BitsClient.html) is the main interface, used to issue commands.
//!
//! [`BitsMonitorClient`](enum.BitsMonitorClient.html) delivers periodic status reports about a
//! job.
//!
//! Microsoft's documentation for BITS can be found at
//! <https://docs.microsoft.com/en-us/windows/desktop/Bits/background-intelligent-transfer-service-portal>

extern crate bits;
extern crate comedy;
extern crate guid_win;
extern crate thiserror;

pub mod bits_protocol;

mod in_process;

use std::ffi;

use bits_protocol::*;
use thiserror::Error;

pub use bits::status::{BitsErrorContext, BitsJobState, BitsJobTimes};
pub use bits::{BitsJobProgress, BitsJobStatus, BitsProxyUsage};
pub use bits_protocol::{JobError, JobStatus};
pub use comedy::HResult;
pub use guid_win::Guid;

// These errors would come from a Local Service client but are mostly unused currently.
// PipeError properly lives in the crate that deals with named pipes, but it isn't in use now.
#[derive(Clone, Debug, Eq, Error, PartialEq)]
pub enum PipeError {
    #[error("Pipe is not connected")]
    NotConnected,
    #[error("Operation timed out")]
    Timeout,
    #[error("Should have written {0} bytes, wrote {1}")]
    WriteCount(usize, u32),
    #[error("Windows API error")]
    Api(HResult),
}

impl From<HResult> for PipeError {
    fn from(value: HResult) -> Self {
        Self::Api(value)
    }
}

pub use PipeError as Error;

/// A client for interacting with BITS.
///
/// Methods on `BitsClient` return a `Result<Result<_, XyzFailure>, Error>`. The outer `Result`
/// is `Err` if there was a communication error in sending the associated command or receiving
/// its response. Currently this is always `Ok` as all clients are in-process. The inner
/// `Result` is `Err` if there was an error executing the command.
///
/// A single `BitsClient` can be used with multiple BITS jobs simultaneously; generally a job
/// is not bound tightly to a client.
///
/// A `BitsClient` tracks all [`BitsMonitorClient`s](enum.BitsMonitorClient.html) that it started
/// with `start_job()` or `monitor_job()`, so that the monitor can be stopped or modified.
pub enum BitsClient {
    // The `InProcess` variant does all BITS calls directly.
    #[doc(hidden)]
    InProcess(in_process::InProcessClient),
    // Space is reserved here for the LocalService variant, which will work through an external
    // process running as Local Service.
}

use BitsClient::InProcess;

impl BitsClient {
    /// Create an in-process `BitsClient`.
    ///
    /// `job_name` will be used when creating jobs, and this `BitsClient` can only be used to
    /// manipulate jobs with that name.
    ///
    /// `save_path_prefix` will be prepended to the local `save_path` given to `start_job()`, it
    /// must name an existing directory.
    pub fn new(
        job_name: ffi::OsString,
        save_path_prefix: ffi::OsString,
    ) -> Result<BitsClient, Error> {
        Ok(InProcess(in_process::InProcessClient::new(
            job_name,
            save_path_prefix,
        )?))
    }

    /// Start a job to download a single file at `url` to local path `save_path` (relative to the
    /// `save_path_prefix` given when constructing the `BitsClient`).
    ///
    /// `save_path_prefix` combined with `save_path` must name a file (existing or not) in an
    /// existing directory, which must be under the directory named by `save_path_prefix`.
    ///
    /// `proxy_usage` determines what proxy will be used.
    ///
    /// When a successful result `Ok(result)` is returned, `result.0.guid` is the id for the
    /// new job, and `result.1` is a monitor client that can be polled for periodic updates,
    /// returning a result approximately once per `monitor_interval_millis` milliseconds.
    pub fn start_job(
        &mut self,
        url: ffi::OsString,
        save_path: ffi::OsString,
        proxy_usage: BitsProxyUsage,
        no_progress_timeout_secs: u32,
        monitor_interval_millis: u32,
        custom_headers: ffi::OsString,
    ) -> Result<Result<(StartJobSuccess, BitsMonitorClient), StartJobFailure>, Error> {
        match self {
            InProcess(client) => Ok(client
                .start_job(
                    url,
                    save_path,
                    proxy_usage,
                    no_progress_timeout_secs,
                    monitor_interval_millis,
                    custom_headers,
                )
                .map(|(success, monitor)| (success, BitsMonitorClient::InProcess(monitor)))),
        }
    }

    /// Start monitoring the job with id `guid` approximately once per `monitor_interval_millis`
    /// milliseconds.
    ///
    /// The returned `Ok(monitor)` is a monitor client to be polled for periodic updates.
    ///
    /// There can only be one ongoing `BitsMonitorClient` for each job associated with a given
    /// `BitsClient`. If a monitor client already exists for the specified job, it will be stopped.
    pub fn monitor_job(
        &mut self,
        guid: Guid,
        interval_millis: u32,
    ) -> Result<Result<BitsMonitorClient, MonitorJobFailure>, Error> {
        match self {
            InProcess(client) => Ok(client
                .monitor_job(guid, interval_millis)
                .map(BitsMonitorClient::InProcess)),
        }
    }

    /// Suspend job `guid`.
    pub fn suspend_job(&mut self, guid: Guid) -> Result<Result<(), SuspendJobFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.suspend_job(guid)),
        }
    }

    /// Resume job `guid`.
    pub fn resume_job(&mut self, guid: Guid) -> Result<Result<(), ResumeJobFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.resume_job(guid)),
        }
    }

    /// Set the priority of job `guid`.
    ///
    /// `foreground == true` will set the priority to `BG_JOB_PRIORITY_FOREGROUND`,
    /// `false` will use the default `BG_JOB_PRIORITY_NORMAL`.
    /// See the Microsoft documentation for `BG_JOB_PRIORITY` for details.
    ///
    /// A job created by `start_job()` will be foreground priority, by default.
    pub fn set_job_priority(
        &mut self,
        guid: Guid,
        foreground: bool,
    ) -> Result<Result<(), SetJobPriorityFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.set_job_priority(guid, foreground)),
        }
    }

    /// Set the "no progress timeout" of job `guid`.
    pub fn set_no_progress_timeout(
        &mut self,
        guid: Guid,
        timeout_secs: u32,
    ) -> Result<Result<(), SetNoProgressTimeoutFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.set_no_progress_timeout(guid, timeout_secs)),
        }
    }

    /// Change the update interval for an ongoing monitor of job `guid`.
    pub fn set_update_interval(
        &mut self,
        guid: Guid,
        interval_millis: u32,
    ) -> Result<Result<(), SetUpdateIntervalFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.set_update_interval(guid, interval_millis)),
        }
    }

    /// Stop any ongoing monitor for job `guid`.
    pub fn stop_update(
        &mut self,
        guid: Guid,
    ) -> Result<Result<(), SetUpdateIntervalFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.stop_update(guid)),
        }
    }

    /// Complete the job `guid`.
    ///
    /// This also stops any ongoing monitor for the job.
    pub fn complete_job(&mut self, guid: Guid) -> Result<Result<(), CompleteJobFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.complete_job(guid)),
        }
    }

    /// Cancel the job `guid`.
    ///
    /// This also stops any ongoing monitor for the job.
    pub fn cancel_job(&mut self, guid: Guid) -> Result<Result<(), CancelJobFailure>, Error> {
        match self {
            InProcess(client) => Ok(client.cancel_job(guid)),
        }
    }
}

/// The client side of a monitor for a BITS job.
///
/// It is intended to be used by calling `get_status` in a loop to receive notifications about
/// the status of a job. Because `get_status` blocks, it is recommended to run this loop on its
/// own thread.
pub enum BitsMonitorClient {
    InProcess(in_process::InProcessMonitor),
}

impl BitsMonitorClient {
    /// `get_status` will return a result approximately every `monitor_interval_millis`
    /// milliseconds, but in case a result isn't available within `timeout_millis` milliseconds
    /// this will return `Err(Error::Timeout)`. Any `Err` returned, including timeout, indicates
    /// that the monitor has been stopped; the `BitsMonitorClient` should then be discarded.
    ///
    /// As with methods on `BitsClient`, `BitsMonitorClient::get_status()` has an inner `Result`
    /// type which indicates an error returned from the server. Any `Err` here also indicates that
    /// the monitor has stopped after yielding the result.
    ///
    /// The first time `get_status` is called it will return a status without any delay.
    ///
    /// If there is an error or the transfer completes, a result may be available sooner than
    /// the monitor interval.
    pub fn get_status(
        &mut self,
        timeout_millis: u32,
    ) -> Result<Result<JobStatus, HResultMessage>, Error> {
        match self {
            BitsMonitorClient::InProcess(client) => client.get_status(timeout_millis),
        }
    }
}

[ Dauer der Verarbeitung: 0.39 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge