1*ffe74184SMartin Algesten #![allow(dead_code)] 2*ffe74184SMartin Algesten 3*ffe74184SMartin Algesten use std::io; 4*ffe74184SMartin Algesten use std::net; 5*ffe74184SMartin Algesten use std::num::ParseIntError; 6*ffe74184SMartin Algesten use std::string::FromUtf8Error; 7*ffe74184SMartin Algesten use thiserror::Error; 8*ffe74184SMartin Algesten 9*ffe74184SMartin Algesten pub type Result<T> = std::result::Result<T, Error>; 10*ffe74184SMartin Algesten 11*ffe74184SMartin Algesten #[derive(Error, Debug, PartialEq)] 12*ffe74184SMartin Algesten #[non_exhaustive] 13*ffe74184SMartin Algesten pub enum Error { 14*ffe74184SMartin Algesten #[error("buffer: full")] 15*ffe74184SMartin Algesten ErrBufferFull, 16*ffe74184SMartin Algesten #[error("buffer: closed")] 17*ffe74184SMartin Algesten ErrBufferClosed, 18*ffe74184SMartin Algesten #[error("buffer: short")] 19*ffe74184SMartin Algesten ErrBufferShort, 20*ffe74184SMartin Algesten #[error("packet too big")] 21*ffe74184SMartin Algesten ErrPacketTooBig, 22*ffe74184SMartin Algesten #[error("i/o timeout")] 23*ffe74184SMartin Algesten ErrTimeout, 24*ffe74184SMartin Algesten #[error("udp: listener closed")] 25*ffe74184SMartin Algesten ErrClosedListener, 26*ffe74184SMartin Algesten #[error("udp: listen queue exceeded")] 27*ffe74184SMartin Algesten ErrListenQueueExceeded, 28*ffe74184SMartin Algesten #[error("udp: listener accept ch closed")] 29*ffe74184SMartin Algesten ErrClosedListenerAcceptCh, 30*ffe74184SMartin Algesten #[error("obs cannot be nil")] 31*ffe74184SMartin Algesten ErrObsCannotBeNil, 32*ffe74184SMartin Algesten #[error("se of closed network connection")] 33*ffe74184SMartin Algesten ErrUseClosedNetworkConn, 34*ffe74184SMartin Algesten #[error("addr is not a net.UDPAddr")] 35*ffe74184SMartin Algesten ErrAddrNotUdpAddr, 36*ffe74184SMartin Algesten #[error("something went wrong with locAddr")] 37*ffe74184SMartin Algesten ErrLocAddr, 38*ffe74184SMartin Algesten #[error("already closed")] 39*ffe74184SMartin Algesten ErrAlreadyClosed, 40*ffe74184SMartin Algesten #[error("no remAddr defined")] 41*ffe74184SMartin Algesten ErrNoRemAddr, 42*ffe74184SMartin Algesten #[error("address already in use")] 43*ffe74184SMartin Algesten ErrAddressAlreadyInUse, 44*ffe74184SMartin Algesten #[error("no such UDPConn")] 45*ffe74184SMartin Algesten ErrNoSuchUdpConn, 46*ffe74184SMartin Algesten #[error("cannot remove unspecified IP by the specified IP")] 47*ffe74184SMartin Algesten ErrCannotRemoveUnspecifiedIp, 48*ffe74184SMartin Algesten #[error("no address assigned")] 49*ffe74184SMartin Algesten ErrNoAddressAssigned, 50*ffe74184SMartin Algesten #[error("1:1 NAT requires more than one mapping")] 51*ffe74184SMartin Algesten ErrNatRequriesMapping, 52*ffe74184SMartin Algesten #[error("length mismtach between mappedIPs and localIPs")] 53*ffe74184SMartin Algesten ErrMismatchLengthIp, 54*ffe74184SMartin Algesten #[error("non-udp translation is not supported yet")] 55*ffe74184SMartin Algesten ErrNonUdpTranslationNotSupported, 56*ffe74184SMartin Algesten #[error("no associated local address")] 57*ffe74184SMartin Algesten ErrNoAssociatedLocalAddress, 58*ffe74184SMartin Algesten #[error("no NAT binding found")] 59*ffe74184SMartin Algesten ErrNoNatBindingFound, 60*ffe74184SMartin Algesten #[error("has no permission")] 61*ffe74184SMartin Algesten ErrHasNoPermission, 62*ffe74184SMartin Algesten #[error("host name must not be empty")] 63*ffe74184SMartin Algesten ErrHostnameEmpty, 64*ffe74184SMartin Algesten #[error("failed to parse IP address")] 65*ffe74184SMartin Algesten ErrFailedToParseIpaddr, 66*ffe74184SMartin Algesten #[error("no interface is available")] 67*ffe74184SMartin Algesten ErrNoInterface, 68*ffe74184SMartin Algesten #[error("not found")] 69*ffe74184SMartin Algesten ErrNotFound, 70*ffe74184SMartin Algesten #[error("unexpected network")] 71*ffe74184SMartin Algesten ErrUnexpectedNetwork, 72*ffe74184SMartin Algesten #[error("can't assign requested address")] 73*ffe74184SMartin Algesten ErrCantAssignRequestedAddr, 74*ffe74184SMartin Algesten #[error("unknown network")] 75*ffe74184SMartin Algesten ErrUnknownNetwork, 76*ffe74184SMartin Algesten #[error("no router linked")] 77*ffe74184SMartin Algesten ErrNoRouterLinked, 78*ffe74184SMartin Algesten #[error("invalid port number")] 79*ffe74184SMartin Algesten ErrInvalidPortNumber, 80*ffe74184SMartin Algesten #[error("unexpected type-switch failure")] 81*ffe74184SMartin Algesten ErrUnexpectedTypeSwitchFailure, 82*ffe74184SMartin Algesten #[error("bind failed")] 83*ffe74184SMartin Algesten ErrBindFailed, 84*ffe74184SMartin Algesten #[error("end port is less than the start")] 85*ffe74184SMartin Algesten ErrEndPortLessThanStart, 86*ffe74184SMartin Algesten #[error("port space exhausted")] 87*ffe74184SMartin Algesten ErrPortSpaceExhausted, 88*ffe74184SMartin Algesten #[error("vnet is not enabled")] 89*ffe74184SMartin Algesten ErrVnetDisabled, 90*ffe74184SMartin Algesten #[error("invalid local IP in static_ips")] 91*ffe74184SMartin Algesten ErrInvalidLocalIpInStaticIps, 92*ffe74184SMartin Algesten #[error("mapped in static_ips is beyond subnet")] 93*ffe74184SMartin Algesten ErrLocalIpBeyondStaticIpsSubset, 94*ffe74184SMartin Algesten #[error("all static_ips must have associated local IPs")] 95*ffe74184SMartin Algesten ErrLocalIpNoStaticsIpsAssociated, 96*ffe74184SMartin Algesten #[error("router already started")] 97*ffe74184SMartin Algesten ErrRouterAlreadyStarted, 98*ffe74184SMartin Algesten #[error("router already stopped")] 99*ffe74184SMartin Algesten ErrRouterAlreadyStopped, 100*ffe74184SMartin Algesten #[error("static IP is beyond subnet")] 101*ffe74184SMartin Algesten ErrStaticIpIsBeyondSubnet, 102*ffe74184SMartin Algesten #[error("address space exhausted")] 103*ffe74184SMartin Algesten ErrAddressSpaceExhausted, 104*ffe74184SMartin Algesten #[error("no IP address is assigned for eth0")] 105*ffe74184SMartin Algesten ErrNoIpaddrEth0, 106*ffe74184SMartin Algesten #[error("Invalid mask")] 107*ffe74184SMartin Algesten ErrInvalidMask, 108*ffe74184SMartin Algesten #[error("parse ipnet: {0}")] 109*ffe74184SMartin Algesten ParseIpnet(#[from] ipnet::AddrParseError), 110*ffe74184SMartin Algesten #[error("parse ip: {0}")] 111*ffe74184SMartin Algesten ParseIp(#[from] net::AddrParseError), 112*ffe74184SMartin Algesten #[error("parse int: {0}")] 113*ffe74184SMartin Algesten ParseInt(#[from] ParseIntError), 114*ffe74184SMartin Algesten #[error("{0}")] 115*ffe74184SMartin Algesten Io(#[source] IoError), 116*ffe74184SMartin Algesten #[error("utf8: {0}")] 117*ffe74184SMartin Algesten Utf8(#[from] FromUtf8Error), 118*ffe74184SMartin Algesten #[error("{0}")] 119*ffe74184SMartin Algesten Std(#[source] StdError), 120*ffe74184SMartin Algesten #[error("{0}")] 121*ffe74184SMartin Algesten Other(String), 122*ffe74184SMartin Algesten } 123*ffe74184SMartin Algesten 124*ffe74184SMartin Algesten impl Error { from_std<T>(error: T) -> Self where T: std::error::Error + Send + Sync + 'static,125*ffe74184SMartin Algesten pub fn from_std<T>(error: T) -> Self 126*ffe74184SMartin Algesten where 127*ffe74184SMartin Algesten T: std::error::Error + Send + Sync + 'static, 128*ffe74184SMartin Algesten { 129*ffe74184SMartin Algesten Error::Std(StdError(Box::new(error))) 130*ffe74184SMartin Algesten } 131*ffe74184SMartin Algesten downcast_ref<T: std::error::Error + 'static>(&self) -> Option<&T>132*ffe74184SMartin Algesten pub fn downcast_ref<T: std::error::Error + 'static>(&self) -> Option<&T> { 133*ffe74184SMartin Algesten if let Error::Std(s) = self { 134*ffe74184SMartin Algesten return s.0.downcast_ref(); 135*ffe74184SMartin Algesten } 136*ffe74184SMartin Algesten 137*ffe74184SMartin Algesten None 138*ffe74184SMartin Algesten } 139*ffe74184SMartin Algesten } 140*ffe74184SMartin Algesten 141*ffe74184SMartin Algesten #[derive(Debug, Error)] 142*ffe74184SMartin Algesten #[error("io error: {0}")] 143*ffe74184SMartin Algesten pub struct IoError(#[from] pub io::Error); 144*ffe74184SMartin Algesten 145*ffe74184SMartin Algesten // Workaround for wanting PartialEq for io::Error. 146*ffe74184SMartin Algesten impl PartialEq for IoError { eq(&self, other: &Self) -> bool147*ffe74184SMartin Algesten fn eq(&self, other: &Self) -> bool { 148*ffe74184SMartin Algesten self.0.kind() == other.0.kind() 149*ffe74184SMartin Algesten } 150*ffe74184SMartin Algesten } 151*ffe74184SMartin Algesten 152*ffe74184SMartin Algesten impl From<io::Error> for Error { from(e: io::Error) -> Self153*ffe74184SMartin Algesten fn from(e: io::Error) -> Self { 154*ffe74184SMartin Algesten Error::Io(IoError(e)) 155*ffe74184SMartin Algesten } 156*ffe74184SMartin Algesten } 157*ffe74184SMartin Algesten 158*ffe74184SMartin Algesten /// An escape hatch to preserve stack traces when we don't know the error. 159*ffe74184SMartin Algesten /// 160*ffe74184SMartin Algesten /// This crate exports some traits such as `Conn` and `Listener`. The trait functions 161*ffe74184SMartin Algesten /// produce the local error `util::Error`. However when used in crates higher up the stack, 162*ffe74184SMartin Algesten /// we are forced to handle errors that are local to that crate. For example we use 163*ffe74184SMartin Algesten /// `Listener` the `dtls` crate and it needs to handle `dtls::Error`. 164*ffe74184SMartin Algesten /// 165*ffe74184SMartin Algesten /// By using `util::Error::from_std` we can preserve the underlying error (and stack trace!). 166*ffe74184SMartin Algesten #[derive(Debug, Error)] 167*ffe74184SMartin Algesten #[error("{0}")] 168*ffe74184SMartin Algesten pub struct StdError(pub Box<dyn std::error::Error + Send + Sync>); 169*ffe74184SMartin Algesten 170*ffe74184SMartin Algesten impl PartialEq for StdError { eq(&self, _: &Self) -> bool171*ffe74184SMartin Algesten fn eq(&self, _: &Self) -> bool { 172*ffe74184SMartin Algesten false 173*ffe74184SMartin Algesten } 174*ffe74184SMartin Algesten } 175