rdp/model/
error.rs

1extern crate native_tls;
2
3use std::io::{Read, Write};
4use std::io::Error as IoError;
5use std::string::String;
6use self::native_tls::HandshakeError;
7use self::native_tls::Error as SslError;
8use yasna::ASN1Error;
9use num_enum::{TryFromPrimitive, TryFromPrimitiveError};
10
11#[derive(Debug, Copy, Clone, Eq, PartialEq)]
12pub enum RdpErrorKind {
13    /// Unexpected data
14    InvalidData,
15    /// Respond from server or client is not valid
16    InvalidRespond,
17    /// Features not implemented
18    NotImplemented,
19    /// During conncetion sequence
20    /// A securtiy level is negotiated
21    /// If no level can be defined a ProtocolNegFailure is emitted
22    ProtocolNegFailure,
23    /// Protocol automata transition is not expected
24    InvalidAutomata,
25    /// A security protocol
26    /// selected was not handled by rdp-rs
27    InvalidProtocol,
28    /// All messages in rdp-rs
29    /// are based on Message trait
30    /// To retrieve the original data we used
31    /// a visitor pattern. If the expected
32    /// type is not found an InvalidCast error is emited
33    InvalidCast,
34    /// If an expected value is not equal
35    InvalidConst,
36    /// During security exchange some
37    /// checksum are computed
38    InvalidChecksum,
39    InvalidOptionalField,
40    InvalidSize,
41    /// A possible Man In The Middle attack
42    /// detected during NLA Authentication
43    PossibleMITM,
44    /// Some channel or user can be rejected
45    /// by server during connection step
46    RejectedByServer,
47    /// Disconnect receive from server
48    Disconnect,
49    /// Indicate an unknown field
50    Unknown,
51    UnexpectedType
52}
53
54#[derive(Debug)]
55pub struct RdpError {
56    /// Kind of error
57    kind: RdpErrorKind,
58    /// Associated message of the context
59    message: String
60}
61
62impl RdpError {
63    /// create a new RDP error
64    /// # Example
65    /// ```
66    /// use rdp::model::error::{RdpError, RdpErrorKind};
67    /// let error = RdpError::new(RdpErrorKind::Disconnect, "disconnected");
68    /// ```
69    pub fn new (kind: RdpErrorKind, message: &str) -> Self {
70        RdpError {
71            kind,
72            message: String::from(message)
73        }
74    }
75
76    /// Return the kind of error
77    ///
78    /// # Example
79    /// ```
80    /// use rdp::model::error::{RdpError, RdpErrorKind};
81    /// let error = RdpError::new(RdpErrorKind::Disconnect, "disconnected");
82    /// assert_eq!(error.kind(), RdpErrorKind::Disconnect)
83    /// ```
84    pub fn kind(&self) -> RdpErrorKind {
85        self.kind
86    }
87}
88
89#[derive(Debug)]
90pub enum Error {
91    /// RDP error
92    RdpError(RdpError),
93    /// All kind of IO error
94    Io(IoError),
95    /// SSL handshake error
96    SslHandshakeError,
97    /// SSL error
98    SslError(SslError),
99    /// ASN1 parser error
100    ASN1Error(ASN1Error),
101    /// try error
102    TryError(String)
103}
104
105/// From IO Error
106impl From<IoError> for Error {
107    fn from(e: IoError) -> Self {
108        Error::Io(e)
109    }
110}
111
112impl<S: Read + Write> From<HandshakeError<S>> for Error {
113    fn from(_: HandshakeError<S>) -> Error {
114        Error::SslHandshakeError
115    }
116}
117
118impl From<SslError> for Error {
119    fn from(e: SslError) -> Error {
120        Error::SslError(e)
121    }
122}
123
124impl From<ASN1Error> for Error {
125    fn from(e: ASN1Error) -> Error {
126        Error::ASN1Error(e)
127    }
128}
129
130impl<T: TryFromPrimitive> From<TryFromPrimitiveError<T>> for Error {
131    fn from(_: TryFromPrimitiveError<T>) -> Self {
132        Error::RdpError(RdpError::new(RdpErrorKind::InvalidCast, "Invalid enum conversion"))
133    }
134}
135
136pub type RdpResult<T> = Result<T, Error>;
137
138/// Try options is waiting try trait for the next rust
139#[macro_export]
140macro_rules! try_option {
141    ($val: expr, $expr: expr) => {
142         if let Some(x) = $val {
143            Ok(x)
144         } else {
145            Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidOptionalField, $expr)))
146         }
147    }
148}
149
150#[macro_export]
151macro_rules! try_let {
152    ($ident: path, $val: expr) => {
153         if let $ident(x) = $val {
154            Ok(x)
155         } else {
156            Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidCast, "Invalid Cast")))
157         }
158    }
159}
160