Skip to main content

harddrive_party_shared/
ui_messages.rs

1//! Messages for communicating with the user interface over websocket
2
3use crate::{announce_address::AnnounceAddressDecodeError, wire_messages::IndexQuery};
4use serde::{Deserialize, Serialize};
5use std::{fmt, time::Duration};
6use thiserror::Error;
7
8#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
9pub struct FilesQuery {
10    pub peer_name: Option<String>,
11    pub query: IndexQuery,
12}
13
14/// 'Events' are messages sent from the server which are not in response to a particular
15/// request - eg: to inform the UI that a peer connected or disconnected
16#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
17pub enum UiEvent {
18    /// A peer has connected
19    PeerConnected { name: String },
20    /// A peer has disconnected
21    PeerDisconnected { name: String, error: String },
22    /// A peer connection failed
23    PeerConnectionFailed { name: String, error: String },
24    /// Part of a file has been uploaded
25    Uploaded(UploadInfo),
26    /// Download
27    Download(DownloadEvent),
28}
29
30#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
31pub struct Info {
32    pub name: String,
33    pub os_home_dir: Option<String>,
34    pub announce_address: String,
35}
36
37/// A request to download a file from a particular peer
38#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
39pub struct UiDownloadRequest {
40    /// The path of the file on the remote
41    pub path: String,
42    /// How much is already downloaded
43    pub progress: u64,
44    /// The total size in bytes
45    pub total_size: u64,
46    /// Identifier for the request
47    pub request_id: u32,
48    /// Time when request made relative to unix epoch
49    pub timestamp: Duration,
50    /// Name of peer who holds file
51    pub peer_name: String,
52}
53
54#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
55pub struct UiRequestedFile {
56    pub path: String,
57    /// The size in bytes
58    pub size: u64,
59    /// This id is not unique - it references which request this came from
60    /// requesting a directory will be split into requests for each file
61    pub request_id: u32,
62    pub downloaded: bool,
63}
64
65/// Information about a current running upload
66#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
67pub struct UploadInfo {
68    pub path: String,
69    pub bytes_read: u64,
70    pub speed: usize,
71    pub peer_name: String,
72}
73
74/// An error in response to a UI command
75#[derive(Serialize, Deserialize, PartialEq, Debug, Error, Clone)]
76pub enum UiServerError {
77    #[error("Cannot connect: {0}")]
78    ConnectionError(String),
79    #[error("Request error: {0}")]
80    RequestError(String),
81    #[error("Error when updating shared directory")]
82    ShareError(String),
83    #[error("Serialization: {0}")]
84    Serialization(String),
85    #[error("Peer discovery: {0}")]
86    PeerDiscovery(String),
87    #[error("Poisoned lock")]
88    Poison,
89    #[error("Database: {0}")]
90    Db(String),
91    #[error("Error adding directory to share: {0}")]
92    AddShare(String),
93    #[error("Cannot decode announce address {0}")]
94    AnnounceAddressDecode(#[from] AnnounceAddressDecodeError),
95}
96
97#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
98pub enum DownloadInfo {
99    Downloading {
100        /// File path of currently downloading file
101        path: String,
102        /// Number of bytes read for this file
103        bytes_read: u64,
104        /// Total number of bytes read from the associated download request
105        total_bytes_read: u64,
106        /// Current speed of download in bytes per second
107        speed: u32,
108    },
109    Completed(Duration),
110}
111
112/// A response to a download request
113#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
114pub struct DownloadEvent {
115    pub request_id: u32,
116    /// File path of requested file of directory
117    pub path: String,
118    /// Name of the peer who holds the file or directory
119    pub peer_name: String,
120    pub download_info: DownloadInfo,
121    // pub total_size: u64,
122}
123
124impl fmt::Display for DownloadEvent {
125    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126        match &self.download_info {
127            DownloadInfo::Downloading {
128                path,
129                bytes_read,
130                total_bytes_read,
131                speed,
132            } => {
133                write!(
134                    f,
135                    "Downloading {}/{} {} bytes read, {} total bytes read, {} bps",
136                    self.peer_name, path, bytes_read, total_bytes_read, speed
137                )
138            }
139            DownloadInfo::Completed(_time) => {
140                write!(f, "Completed {}/{}", self.peer_name, self.path)
141            }
142        }
143    }
144}
145
146/// Represents a remote file
147#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
148pub struct PeerPath {
149    /// The name of the peer who holds the file
150    pub peer_name: String,
151    /// The path to the remote file
152    pub path: String,
153}