Skip to main content

lzc_sdk/
error.rs

1use std::io;
2use std::path::PathBuf;
3
4use thiserror::Error;
5use tonic::metadata::errors::InvalidMetadataValue;
6
7/// Errors returned by the `LazyCat` SDK compatibility layer.
8#[derive(Debug, Error)]
9#[non_exhaustive]
10pub enum Error {
11    /// A runtime credential could not be read.
12    #[error("failed to read credential at {path}: {source}")]
13    CredentialRead {
14        /// Credential path that failed.
15        path: PathBuf,
16        /// Underlying I/O failure.
17        #[source]
18        source: io::Error,
19    },
20
21    /// A certificate file was empty, malformed, or unsupported.
22    #[error("invalid certificate at {path}: {reason}")]
23    InvalidCertificate {
24        /// Certificate path that failed validation.
25        path: PathBuf,
26        /// Sanitized validation reason.
27        reason: &'static str,
28    },
29
30    /// A private key file was empty, malformed, unsupported, or mismatched.
31    #[error("invalid private key at {path}: {reason}")]
32    InvalidPrivateKey {
33        /// Private key path that failed validation.
34        path: PathBuf,
35        /// Sanitized validation reason.
36        reason: &'static str,
37    },
38
39    /// A tonic channel could not be configured or connected.
40    #[error("gRPC transport error: {0}")]
41    Transport(#[from] tonic::transport::Error),
42
43    /// A gRPC method returned a status response.
44    #[error("gRPC request failed: {0}")]
45    GrpcStatus(#[from] tonic::Status),
46
47    /// The runtime gateway override is not a host or HTTP(S) URI.
48    #[error("invalid runtime API gateway address")]
49    InvalidGatewayAddress,
50
51    /// A device API URL is malformed or uses an unsupported scheme.
52    #[error("invalid LazyCat device API URL")]
53    InvalidDeviceUrl,
54
55    /// The application private key cannot produce Go-compatible auth signatures.
56    #[error("unsupported application private key for device authentication")]
57    UnsupportedAuthSigningKey,
58
59    /// Signing the application identity failed.
60    #[error("failed to sign the application identity")]
61    AuthSigning,
62
63    /// The device returned a token without an expiry deadline.
64    #[error("device auth token response has no deadline")]
65    MissingTokenDeadline,
66
67    /// The device returned an invalid token expiry deadline.
68    #[error("device auth token response has an invalid deadline")]
69    InvalidTokenDeadline,
70
71    /// An auth token cannot be encoded as gRPC metadata.
72    #[error("device auth token is not a valid gRPC metadata value")]
73    InvalidAuthTokenMetadata,
74
75    /// The device does not implement the optional service-status API.
76    #[error("device service-status query is unsupported")]
77    ServiceStatusUnsupported,
78
79    /// `HPortalSys` returned a malformed or unsupported `RemoteSocks` URL.
80    #[error("HPortalSys returned an invalid RemoteSocks endpoint")]
81    InvalidRemoteSocksEndpoint,
82
83    /// Resolving the `LazyCat` host-service address failed.
84    #[error("failed to resolve host.lzcapp: {source}")]
85    ServiceAddressLookup {
86        /// Underlying DNS lookup failure.
87        #[source]
88        source: io::Error,
89    },
90
91    /// No resolved host-service candidate had a usable local route.
92    #[error("no usable route to host.lzcapp")]
93    ServiceAddressNoRoute {
94        /// Last route-selection failure, when at least one candidate was tried.
95        #[source]
96        source: Option<io::Error>,
97    },
98
99    /// A SOCKS address is malformed or cannot be represented on the wire.
100    #[error("invalid SOCKS address")]
101    InvalidSocksAddress,
102
103    /// A SOCKS domain or custom address exceeds the one-byte wire length.
104    #[error("SOCKS address is longer than 255 bytes")]
105    SocksAddressTooLong,
106
107    /// A SOCKS peer used an address type not defined by RFC 1928.
108    #[error("unsupported SOCKS address type {address_type:#04x}")]
109    UnsupportedSocksAddressType {
110        /// Unrecognized wire address type.
111        address_type: u8,
112    },
113
114    /// A network operation used by `RemoteSocks` failed.
115    #[error("RemoteSocks network error: {0}")]
116    RemoteSocksIo(#[from] io::Error),
117
118    /// Connecting to the `RemoteSocks` proxy exceeded the configured deadline.
119    #[error("RemoteSocks connection timed out")]
120    RemoteSocksTimeout,
121
122    /// A SOCKS peer replied with an unexpected protocol version.
123    #[error("unexpected SOCKS protocol version {version}")]
124    UnexpectedSocksVersion {
125        /// Version byte received from the peer.
126        version: u8,
127    },
128
129    /// A SOCKS peer rejected every offered authentication method.
130    #[error("SOCKS proxy rejected all authentication methods")]
131    SocksNoAcceptableAuthentication,
132
133    /// A SOCKS peer selected an authentication method this SDK does not support.
134    #[error("unsupported SOCKS authentication method {method:#04x}")]
135    UnsupportedSocksAuthentication {
136        /// Authentication method selected by the peer.
137        method: u8,
138    },
139
140    /// A SOCKS reply used a non-zero reserved byte.
141    #[error("invalid SOCKS reserved byte {reserved:#04x}")]
142    InvalidSocksReservedByte {
143        /// Reserved byte received from the peer.
144        reserved: u8,
145    },
146
147    /// A SOCKS command failed with the provided RFC 1928 reply code.
148    #[error("SOCKS proxy command failed with reply code {code:#04x}")]
149    SocksReply {
150        /// SOCKS reply code returned by the peer.
151        code: u8,
152    },
153
154    /// A SOCKS UDP datagram had invalid reserved or framing bytes.
155    #[error("invalid SOCKS UDP datagram header")]
156    InvalidSocksUdpHeader,
157
158    /// SOCKS UDP fragmentation is not supported by this SDK.
159    #[error("SOCKS UDP fragmentation is unsupported (fragment {fragment})")]
160    UnsupportedSocksUdpFragment {
161        /// Non-zero RFC 1928 fragment byte.
162        fragment: u8,
163    },
164
165    /// A UDP payload cannot fit in one transport frame.
166    #[error("RemoteSocks UDP payload is too large")]
167    SocksUdpPayloadTooLarge,
168
169    /// An operation requiring a fixed UDP peer was used on a bound socket.
170    #[error("RemoteSocks UDP socket has no connected peer")]
171    SocksUdpNotConnected,
172
173    /// The `RemoteSocks` TCP control stream has closed.
174    #[error("RemoteSocks UDP control stream closed")]
175    RemoteSocksControlClosed,
176
177    /// A SOCKS address cannot be used as a concrete UDP socket address.
178    #[error("invalid RemoteSocks UDP socket address")]
179    InvalidSocksUdpAddress,
180
181    /// A value cannot be represented as gRPC metadata.
182    #[error("invalid gRPC metadata value")]
183    InvalidMetadataValue(#[source] InvalidMetadataValue),
184
185    /// The request was not received over authenticated TLS.
186    #[error("peer is not authenticated with a TLS client certificate")]
187    UnauthenticatedPeer,
188
189    /// `LazyCat` application identity requires exactly one peer certificate.
190    #[error("expected exactly one peer certificate, got {count}")]
191    InvalidPeerCertificateCount {
192        /// Number of certificates presented by the peer.
193        count: usize,
194    },
195
196    /// The peer certificate could not be decoded as X.509.
197    #[error("invalid peer certificate")]
198    InvalidPeerCertificate,
199}