Skip to main content

runsync_transfer/
error.rs

1use std::io;
2
3/// Errors produced by the transfer engine.
4#[derive(Debug, thiserror::Error)]
5pub enum Error {
6    #[error("io: {0}")]
7    Io(#[from] io::Error),
8
9    #[error("transport: {0}")]
10    Transport(String),
11
12    /// Peer closed the connection or a stream before the message was complete.
13    #[error("peer closed the connection: {0}")]
14    Closed(String),
15
16    #[error("protocol violation: {0}")]
17    Protocol(String),
18
19    /// Version negotiation failed: the peer speaks a wire version we cannot serve.
20    #[error("unsupported wire version {peer} (we support {ours})")]
21    Version { peer: u16, ours: u16 },
22
23    #[error("handshake failed: {0}")]
24    Handshake(String),
25
26    /// AEAD tag mismatch, truncated ciphertext, or a nonce we refuse to reuse.
27    #[error("decryption failed for file {file_id} chunk {chunk}")]
28    Decrypt { file_id: u32, chunk: u64 },
29
30    #[error("compression: {0}")]
31    Compress(String),
32
33    /// Content hash of a received file did not match what the sender advertised.
34    #[error("integrity check failed for {path}: expected {expected}, got {actual}")]
35    Integrity {
36        path: String,
37        expected: String,
38        actual: String,
39    },
40
41    /// A frame declared a length outside the configured limits. Guards against a
42    /// hostile peer driving us into an unbounded allocation.
43    #[error("frame too large: {got} bytes exceeds limit {limit}")]
44    FrameTooLarge { got: usize, limit: usize },
45
46    #[error("configuration: {0}")]
47    Config(String),
48
49    #[error("path {0:?} escapes the destination root")]
50    UnsafePath(std::path::PathBuf),
51
52    #[error("transfer cancelled")]
53    Cancelled,
54
55    #[error("worker panicked: {0}")]
56    Worker(String),
57}
58
59impl Error {
60    // Only the bundled transports construct this; a build with every transport
61    // feature off still wants the variant available to downstream adapters.
62    #[allow(dead_code)]
63    pub(crate) fn transport(e: impl std::fmt::Display) -> Self {
64        Error::Transport(e.to_string())
65    }
66    pub(crate) fn protocol(e: impl Into<String>) -> Self {
67        Error::Protocol(e.into())
68    }
69}
70
71pub type Result<T> = std::result::Result<T, Error>;