use crate::packet::ReferenceIdentifier;
use std::convert::From;
use std::error::Error;
use std::fmt::{Display, Formatter};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum KissCode {
Unknown,
AssociationBelongsToAnycastServer,
AssociationBelongsToBroadcastServer,
AssociationBelongsToManycastServer,
ServerAuthenticationFailed,
AutokeySequenceFailed,
CryptographicAuthenticationFailed,
AccessDenied,
LostPeer,
AssociationNotYetSynchronized,
NoKeyFound,
RateExceeded,
TinkeringWithAssociation,
StepChange,
}
impl KissCode {
pub(crate) fn new(reference_identifier: &ReferenceIdentifier) -> KissCode {
if let ReferenceIdentifier::ASCII(s) = reference_identifier {
match s.as_str() {
"ACST" => KissCode::AssociationBelongsToAnycastServer,
"AUTH" => KissCode::ServerAuthenticationFailed,
"AUTO" => KissCode::AutokeySequenceFailed,
"BCST" => KissCode::AssociationBelongsToBroadcastServer,
"CRYP" => KissCode::CryptographicAuthenticationFailed,
"DENY" => KissCode::AccessDenied,
"DROP" => KissCode::LostPeer,
"RSTR" => KissCode::AccessDenied,
"INIT" => KissCode::AssociationNotYetSynchronized,
"MCST" => KissCode::AssociationBelongsToManycastServer,
"NKEY" => KissCode::NoKeyFound,
"RATE" => KissCode::RateExceeded,
"RMOT" => KissCode::TinkeringWithAssociation,
"STEP" => KissCode::StepChange,
_ => KissCode::Unknown,
}
} else {
KissCode::Unknown
}
}
}
impl Display for KissCode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
KissCode::Unknown => write!(f, "Unknown"),
KissCode::AssociationBelongsToAnycastServer => {
write!(f, "The association belongs to a anycast server")
}
KissCode::AssociationBelongsToBroadcastServer => {
write!(f, "The association belongs to a broadcast server")
}
KissCode::AssociationBelongsToManycastServer => {
write!(f, "The association belongs to a manycast server")
}
KissCode::ServerAuthenticationFailed => write!(f, "Server authentication failed"),
KissCode::AutokeySequenceFailed => write!(f, "Autokey sequence failed"),
KissCode::CryptographicAuthenticationFailed => {
write!(f, "Cryptographic authentication or identification failed")
}
KissCode::AccessDenied => write!(f, "Access denied by remote server"),
KissCode::LostPeer => write!(f, "Lost peer in symmetric mode"),
KissCode::AssociationNotYetSynchronized => write!(
f,
"The association has not yet synchronized for the first time"
),
KissCode::NoKeyFound => write!(
f,
"No key found. Either the key was never installed or is not trusted"
),
KissCode::RateExceeded => write!(f, "Rate exceeded. The server has temporarily denied access because the client exceeded the rate threshold"),
KissCode::TinkeringWithAssociation => write!(f, "Somebody is tinkering with the association from a remote host"),
KissCode::StepChange => write!(f, " step change in system time has occurred, but the association has not yet resynchronized"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ProtocolError {
PacketIsTooShort,
InvalidPacketVersion,
InvalidLeapIndicator,
InvalidMode,
InvalidOriginateTimestamp,
InvalidTransmitTimestamp,
InvalidReferenceIdentifier,
KissODeath(KissCode),
}
impl Error for ProtocolError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}
impl Display for ProtocolError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ProtocolError::PacketIsTooShort => write!(f, "Server reply packet is too short"),
ProtocolError::InvalidPacketVersion => {
write!(f, "Server reply packet has unsupported version")
}
ProtocolError::InvalidLeapIndicator => {
write!(f, "Server reply packet contains invalid leap indicator")
}
ProtocolError::InvalidMode => write!(f, "Server reply packet contains invalid mode"),
ProtocolError::InvalidOriginateTimestamp => {
write!(f, "Server reply contains invalid originate timestamp")
}
ProtocolError::InvalidTransmitTimestamp => {
write!(f, "Server reply contains invalid transmit timestamp")
}
ProtocolError::InvalidReferenceIdentifier => {
write!(f, "Server reply contains invalid reference identifier")
}
ProtocolError::KissODeath(code) => {
write!(f, "Kiss-o'-Death packet received: {}", code.to_string())
}
}
}
}
#[derive(Debug)]
pub enum SynchroniztationError {
IOError(std::io::Error),
ProtocolError(ProtocolError),
}
impl Error for SynchroniztationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
SynchroniztationError::IOError(io_error) => Some(io_error),
SynchroniztationError::ProtocolError(protocol_error) => Some(protocol_error),
}
}
}
impl Display for SynchroniztationError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SynchroniztationError::IOError(io_error) => {
write!(f, "Input/output error: {}", io_error.to_string())
}
SynchroniztationError::ProtocolError(protocol_error) => {
write!(f, "Protocol error: {}", protocol_error.to_string())
}
}
}
}
impl From<std::io::Error> for SynchroniztationError {
fn from(io_error: std::io::Error) -> SynchroniztationError {
SynchroniztationError::IOError(io_error)
}
}
impl From<ProtocolError> for SynchroniztationError {
fn from(protocol_error: ProtocolError) -> SynchroniztationError {
SynchroniztationError::ProtocolError(protocol_error)
}
}