1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
pub mod connect;
mod cookie;
mod hsv5;
pub mod listen;
pub mod rendezvous;

use crate::{
    crypto::CryptoOptions,
    packet::{ControlTypes, HandshakeControlInfo, RejectReason},
    Connection, DataPacket, Packet, SeqNumber, SocketID,
};
use rand::random;
use std::{error::Error, fmt, net::SocketAddr, time::Duration};

#[non_exhaustive]
#[derive(Debug)]
pub enum ConnectError {
    ControlExpected(DataPacket),
    HandshakeExpected(ControlTypes),
    InductionExpected(HandshakeControlInfo),
    UnexpectedHost(SocketAddr, SocketAddr),
    ConclusionExpected(HandshakeControlInfo),
    UnsupportedProtocolVersion(u32),
    InvalidHandshakeCookie(i32, i32),
    RendezvousExpected(HandshakeControlInfo),
    CookiesMatched(i32),
    ExpectedHSReq,
    ExpectedHSResp,
    ExpectedExtFlags,
    ExpectedNoExtFlags,
}

#[derive(Debug)]
pub enum ConnectionReject {
    /// local rejected remote
    Rejecting(RejectReason),

    /// remote rejected local
    Rejected(RejectReason),
}

#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ConnectionResult {
    NotHandled(ConnectError),
    Reject(Option<(Packet, SocketAddr)>, ConnectionReject),
    SendPacket((Packet, SocketAddr)),
    Connected(Option<(Packet, SocketAddr)>, Connection),
    NoAction,
}

#[derive(Debug, Clone)]
pub struct ConnInitSettings {
    pub starting_send_seqnum: SeqNumber,
    pub local_sockid: SocketID,
    pub crypto: Option<CryptoOptions>,
    pub send_latency: Duration,
    pub recv_latency: Duration,
}

impl fmt::Display for ConnectError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use ConnectError::*;
        match self {
            ControlExpected(pack) => write!(f, "Expected Control packet, found {:?}", pack),
            HandshakeExpected(got) => write!(f, "Expected Handshake packet, found: {:?}", got),
            InductionExpected(got) => write!(f, "Expected Induction (1) packet, found: {:?}", got),
            UnexpectedHost(host, got) => write!(
                f,
                "Expected packets from different host, expected: {} found: {}",
                host, got
            ),
            ConclusionExpected(got) => {
                write!(f, "Expected Conclusion (-1) packet, found: {:?}", got)
            }
            UnsupportedProtocolVersion(got) => write!(
                f,
                "Unsupported protocol version, expected: v5 found v{0}",
                got
            ),
            InvalidHandshakeCookie(expected, got) => write!(
                f,
                "Received invalid cookie, expected {}, got {}",
                expected, got
            ),
            RendezvousExpected(got) => write!(f, "Expected rendezvous packet, got {:?}", got),
            CookiesMatched(cookie) => write!(
                f,
                "Cookies matched, waiting for a new cookie to resolve contest. Cookie: {}",
                cookie
            ),
            ExpectedHSReq => write!(
                f,
                "Responder got handshake flags, but expected request, not response"
            ),
            ExpectedHSResp => write!(
                f,
                "Initiator got handshake flags, but expected response, not request"
            ),
            ExpectedExtFlags => write!(f, "Responder expected handshake flags, but got none"),
            ExpectedNoExtFlags => {
                write!(f, "Initiator did not expect handshake flags, but got some")
            }
        }
    }
}

impl Error for ConnectError {}

impl fmt::Display for ConnectionReject {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use ConnectionReject::*;
        match self {
            Rejecting(rr) => write!(f, "Local server rejected remote: {}", rr),
            Rejected(rr) => write!(f, "Remote rejected connection: {}", rr),
        }
    }
}

impl ConnectionReject {
    fn reason(&self) -> RejectReason {
        match self {
            ConnectionReject::Rejecting(r) | ConnectionReject::Rejected(r) => *r,
        }
    }
}

impl Error for ConnectionReject {}

impl Default for ConnInitSettings {
    fn default() -> Self {
        ConnInitSettings {
            crypto: None,
            send_latency: Duration::from_millis(50),
            recv_latency: Duration::from_micros(50),
            starting_send_seqnum: random(),
            local_sockid: random(),
        }
    }
}
impl ConnInitSettings {
    pub fn copy_randomize(&self) -> ConnInitSettings {
        ConnInitSettings {
            crypto: self.crypto.clone(),
            send_latency: self.send_latency,
            recv_latency: self.recv_latency,
            starting_send_seqnum: random(),
            local_sockid: random(),
        }
    }
}