Some checks failed
Native code generation / deterministic (push) Failing after 2m18s
Imaging and meshing gate / native (push) Failing after 1m30s
JPEG 2000 feature / linux (push) Successful in 2m40s
Native Rust workspace compile / compile (push) Failing after 57s
Skia feature / linux (push) Successful in 31m8s
227 lines
5.6 KiB
Rust
227 lines
5.6 KiB
Rust
//! 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<u8>,
|
|
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<Self, Error> {
|
|
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<Simulator>,
|
|
pub source: SourceType,
|
|
pub status: StatusCode,
|
|
pub target: TargetType,
|
|
pub next_packet: i32,
|
|
pub out_of_order_packets: RwLock<HashMap<i32, Vec<u8>>>,
|
|
pub base: Transfer,
|
|
}
|
|
impl AssetDownload {
|
|
pub fn new() -> Result<Self, Error> {
|
|
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<u16, u16>,
|
|
pub priority: f32,
|
|
pub simulator: Option<Simulator>,
|
|
pub base: Transfer,
|
|
}
|
|
|
|
impl ImageDownload {
|
|
pub fn new() -> Result<Self, Error> {
|
|
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<Self, Error> {
|
|
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<Self, Error> {
|
|
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<Self, Error> {
|
|
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<Self, Error> {
|
|
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<Self, Error> {
|
|
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<Self, Error> {
|
|
Ok(Self { xfer })
|
|
}
|
|
pub fn xfer(&self) -> XferDownload {
|
|
self.xfer.clone()
|
|
}
|
|
}
|