//! Asset transfer state shared by HTTP and LLUDP pipelines. #![allow(clippy::missing_errors_doc, clippy::must_use_candidate)] use crate::{ ChannelType, Error, ImageCodec, ImageType, Simulator, SourceType, StatusCode, TargetType, TransferError, }; use libremetaverse_types::compat::SortedList; use libremetaverse_types::{AssetType, UUID}; use std::collections::HashMap; use std::sync::RwLock; use std::time::Instant; #[derive(Clone, Debug)] pub struct Transfer { pub asset_data: Vec, pub asset_type: AssetType, pub id: UUID, pub size: i32, pub success: bool, pub transferred: i32, pub(crate) last_packet: Instant, } impl Transfer { pub fn new() -> Result { Ok(Self { asset_data: Vec::new(), asset_type: AssetType::Unknown, id: UUID::zero(), size: 0, success: false, transferred: 0, last_packet: Instant::now(), }) } pub fn time_since_last_packet(&self) -> i32 { i32::try_from(self.last_packet.elapsed().as_millis()).unwrap_or(i32::MAX) } pub fn set_time_since_last_packet(&mut self, value: i32) { self.last_packet = Instant::now() .checked_sub(std::time::Duration::from_millis( u64::try_from(value.max(0)).unwrap_or(0), )) .unwrap_or_else(Instant::now); } } #[derive(Debug)] pub struct AssetDownload { pub asset_id: UUID, pub channel: ChannelType, pub priority: f32, pub simulator: Option, pub source: SourceType, pub status: StatusCode, pub target: TargetType, pub next_packet: i32, pub out_of_order_packets: RwLock>>, pub base: Transfer, } impl AssetDownload { pub fn new() -> Result { Ok(Self { asset_id: UUID::zero(), channel: ChannelType::Asset, priority: 0.0, simulator: None, source: SourceType::Asset, status: StatusCode::Unknown, target: TargetType::Unknown, next_packet: 0, out_of_order_packets: RwLock::new(HashMap::new()), base: Transfer::new()?, }) } } #[derive(Debug)] pub struct ImageDownload { pub codec: ImageCodec, pub discard_level: i32, pub image_type: ImageType, pub packet_count: u16, pub packets_seen: SortedList, pub priority: f32, pub simulator: Option, pub base: Transfer, } impl ImageDownload { pub fn new() -> Result { Ok(Self { codec: ImageCodec::Invalid, discard_level: 0, image_type: ImageType::Normal, packet_count: 0, packets_seen: SortedList(std::collections::BTreeMap::new()), priority: 0.0, simulator: None, base: Transfer::new()?, }) } } #[derive(Clone, Debug)] pub struct AssetUpload { pub asset_id: UUID, pub packet_num: u32, pub type_: AssetType, pub xfer_id: u64, pub base: Transfer, } impl AssetUpload { pub fn new() -> Result { Ok(Self { asset_id: UUID::zero(), packet_num: 0, type_: AssetType::Unknown, xfer_id: 0, base: Transfer::new()?, }) } } #[derive(Clone, Debug)] pub struct AssetUploadEventArgs { upload: AssetUpload, } impl AssetUploadEventArgs { pub fn new(upload: AssetUpload) -> Result { Ok(Self { upload }) } pub fn upload(&self) -> AssetUpload { self.upload.clone() } } #[derive(Clone, Debug)] pub struct ImageReceiveProgressEventArgs { image_id: UUID, received: i32, total: i32, } impl ImageReceiveProgressEventArgs { pub fn new(image_id: UUID, received: i32, total: i32) -> Result { if received < 0 || total < 0 || received > total { return Err(Error::Argument); } Ok(Self { image_id, received, total, }) } pub const fn image_id(&self) -> UUID { self.image_id } pub const fn received(&self) -> i32 { self.received } pub const fn total(&self) -> i32 { self.total } } #[derive(Clone, Debug)] pub struct InitiateDownloadEventArgs { sim_filename: String, viewer_filename: String, } impl InitiateDownloadEventArgs { pub fn new(sim_filename: String, viewer_filename: String) -> Result { if sim_filename.as_bytes().contains(&0) || viewer_filename.as_bytes().contains(&0) { return Err(Error::Argument); } Ok(Self { sim_filename, viewer_filename, }) } pub fn sim_file_name(&self) -> String { self.sim_filename.clone() } pub fn viewer_file_name(&self) -> String { self.viewer_filename.clone() } } #[derive(Clone, Debug)] pub struct XferDownload { pub error: TransferError, pub filename: String, pub packet_num: u32, pub v_file_id: UUID, pub xfer_id: u64, pub base: Transfer, } impl XferDownload { pub fn new() -> Result { Ok(Self { error: TransferError::None, filename: String::new(), packet_num: 0, v_file_id: UUID::zero(), xfer_id: 0, base: Transfer::new()?, }) } } #[derive(Clone, Debug)] pub struct XferReceivedEventArgs { xfer: XferDownload, } impl XferReceivedEventArgs { pub fn new(xfer: XferDownload) -> Result { Ok(Self { xfer }) } pub fn xfer(&self) -> XferDownload { self.xfer.clone() } }