1*ffe74184SMartin Algesten use thiserror::Error; 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::time::SystemTimeError; 7*ffe74184SMartin Algesten 8*ffe74184SMartin Algesten pub type Result<T> = std::result::Result<T, Error>; 9*ffe74184SMartin Algesten 10*ffe74184SMartin Algesten #[derive(Debug, Error, PartialEq)] 11*ffe74184SMartin Algesten #[non_exhaustive] 12*ffe74184SMartin Algesten pub enum Error { 13*ffe74184SMartin Algesten /// Indicates an error with Unknown info. 14*ffe74184SMartin Algesten #[error("Unknown type")] 15*ffe74184SMartin Algesten ErrUnknownType, 16*ffe74184SMartin Algesten 17*ffe74184SMartin Algesten /// Indicates the scheme type could not be parsed. 18*ffe74184SMartin Algesten #[error("unknown scheme type")] 19*ffe74184SMartin Algesten ErrSchemeType, 20*ffe74184SMartin Algesten 21*ffe74184SMartin Algesten /// Indicates query arguments are provided in a STUN URL. 22*ffe74184SMartin Algesten #[error("queries not supported in stun address")] 23*ffe74184SMartin Algesten ErrStunQuery, 24*ffe74184SMartin Algesten 25*ffe74184SMartin Algesten /// Indicates an malformed query is provided. 26*ffe74184SMartin Algesten #[error("invalid query")] 27*ffe74184SMartin Algesten ErrInvalidQuery, 28*ffe74184SMartin Algesten 29*ffe74184SMartin Algesten /// Indicates malformed hostname is provided. 30*ffe74184SMartin Algesten #[error("invalid hostname")] 31*ffe74184SMartin Algesten ErrHost, 32*ffe74184SMartin Algesten 33*ffe74184SMartin Algesten /// Indicates malformed port is provided. 34*ffe74184SMartin Algesten #[error("invalid port number")] 35*ffe74184SMartin Algesten ErrPort, 36*ffe74184SMartin Algesten 37*ffe74184SMartin Algesten /// Indicates local username fragment insufficient bits are provided. 38*ffe74184SMartin Algesten /// Have to be at least 24 bits long. 39*ffe74184SMartin Algesten #[error("local username fragment is less than 24 bits long")] 40*ffe74184SMartin Algesten ErrLocalUfragInsufficientBits, 41*ffe74184SMartin Algesten 42*ffe74184SMartin Algesten /// Indicates local passoword insufficient bits are provided. 43*ffe74184SMartin Algesten /// Have to be at least 128 bits long. 44*ffe74184SMartin Algesten #[error("local password is less than 128 bits long")] 45*ffe74184SMartin Algesten ErrLocalPwdInsufficientBits, 46*ffe74184SMartin Algesten 47*ffe74184SMartin Algesten /// Indicates an unsupported transport type was provided. 48*ffe74184SMartin Algesten #[error("invalid transport protocol type")] 49*ffe74184SMartin Algesten ErrProtoType, 50*ffe74184SMartin Algesten 51*ffe74184SMartin Algesten /// Indicates the agent is closed. 52*ffe74184SMartin Algesten #[error("the agent is closed")] 53*ffe74184SMartin Algesten ErrClosed, 54*ffe74184SMartin Algesten 55*ffe74184SMartin Algesten /// Indicates agent does not have a valid candidate pair. 56*ffe74184SMartin Algesten #[error("no candidate pairs available")] 57*ffe74184SMartin Algesten ErrNoCandidatePairs, 58*ffe74184SMartin Algesten 59*ffe74184SMartin Algesten /// Indicates agent connection was canceled by the caller. 60*ffe74184SMartin Algesten #[error("connecting canceled by caller")] 61*ffe74184SMartin Algesten ErrCanceledByCaller, 62*ffe74184SMartin Algesten 63*ffe74184SMartin Algesten /// Indicates agent was started twice. 64*ffe74184SMartin Algesten #[error("attempted to start agent twice")] 65*ffe74184SMartin Algesten ErrMultipleStart, 66*ffe74184SMartin Algesten 67*ffe74184SMartin Algesten /// Indicates agent was started with an empty remote ufrag. 68*ffe74184SMartin Algesten #[error("remote ufrag is empty")] 69*ffe74184SMartin Algesten ErrRemoteUfragEmpty, 70*ffe74184SMartin Algesten 71*ffe74184SMartin Algesten /// Indicates agent was started with an empty remote pwd. 72*ffe74184SMartin Algesten #[error("remote pwd is empty")] 73*ffe74184SMartin Algesten ErrRemotePwdEmpty, 74*ffe74184SMartin Algesten 75*ffe74184SMartin Algesten /// Indicates agent was started without on_candidate. 76*ffe74184SMartin Algesten #[error("no on_candidate provided")] 77*ffe74184SMartin Algesten ErrNoOnCandidateHandler, 78*ffe74184SMartin Algesten 79*ffe74184SMartin Algesten /// Indicates GatherCandidates has been called multiple times. 80*ffe74184SMartin Algesten #[error("attempting to gather candidates during gathering state")] 81*ffe74184SMartin Algesten ErrMultipleGatherAttempted, 82*ffe74184SMartin Algesten 83*ffe74184SMartin Algesten /// Indicates agent was give TURN URL with an empty Username. 84*ffe74184SMartin Algesten #[error("username is empty")] 85*ffe74184SMartin Algesten ErrUsernameEmpty, 86*ffe74184SMartin Algesten 87*ffe74184SMartin Algesten /// Indicates agent was give TURN URL with an empty Password. 88*ffe74184SMartin Algesten #[error("password is empty")] 89*ffe74184SMartin Algesten ErrPasswordEmpty, 90*ffe74184SMartin Algesten 91*ffe74184SMartin Algesten /// Indicates we were unable to parse a candidate address. 92*ffe74184SMartin Algesten #[error("failed to parse address")] 93*ffe74184SMartin Algesten ErrAddressParseFailed, 94*ffe74184SMartin Algesten 95*ffe74184SMartin Algesten /// Indicates that non host candidates were selected for a lite agent. 96*ffe74184SMartin Algesten #[error("lite agents must only use host candidates")] 97*ffe74184SMartin Algesten ErrLiteUsingNonHostCandidates, 98*ffe74184SMartin Algesten 99*ffe74184SMartin Algesten /// Indicates that one or more URL was provided to the agent but no host candidate required them. 100*ffe74184SMartin Algesten #[error("agent does not need URL with selected candidate types")] 101*ffe74184SMartin Algesten ErrUselessUrlsProvided, 102*ffe74184SMartin Algesten 103*ffe74184SMartin Algesten /// Indicates that the specified NAT1To1IPCandidateType is unsupported. 104*ffe74184SMartin Algesten #[error("unsupported 1:1 NAT IP candidate type")] 105*ffe74184SMartin Algesten ErrUnsupportedNat1to1IpCandidateType, 106*ffe74184SMartin Algesten 107*ffe74184SMartin Algesten /// Indicates that the given 1:1 NAT IP mapping is invalid. 108*ffe74184SMartin Algesten #[error("invalid 1:1 NAT IP mapping")] 109*ffe74184SMartin Algesten ErrInvalidNat1to1IpMapping, 110*ffe74184SMartin Algesten 111*ffe74184SMartin Algesten /// IPNotFound in NAT1To1IPMapping. 112*ffe74184SMartin Algesten #[error("external mapped IP not found")] 113*ffe74184SMartin Algesten ErrExternalMappedIpNotFound, 114*ffe74184SMartin Algesten 115*ffe74184SMartin Algesten /// Indicates that the mDNS gathering cannot be used along with 1:1 NAT IP mapping for host 116*ffe74184SMartin Algesten /// candidate. 117*ffe74184SMartin Algesten #[error("mDNS gathering cannot be used with 1:1 NAT IP mapping for host candidate")] 118*ffe74184SMartin Algesten ErrMulticastDnsWithNat1to1IpMapping, 119*ffe74184SMartin Algesten 120*ffe74184SMartin Algesten /// Indicates that 1:1 NAT IP mapping for host candidate is requested, but the host candidate 121*ffe74184SMartin Algesten /// type is disabled. 122*ffe74184SMartin Algesten #[error("1:1 NAT IP mapping for host candidate ineffective")] 123*ffe74184SMartin Algesten ErrIneffectiveNat1to1IpMappingHost, 124*ffe74184SMartin Algesten 125*ffe74184SMartin Algesten /// Indicates that 1:1 NAT IP mapping for srflx candidate is requested, but the srflx candidate 126*ffe74184SMartin Algesten /// type is disabled. 127*ffe74184SMartin Algesten #[error("1:1 NAT IP mapping for srflx candidate ineffective")] 128*ffe74184SMartin Algesten ErrIneffectiveNat1to1IpMappingSrflx, 129*ffe74184SMartin Algesten 130*ffe74184SMartin Algesten /// Indicates an invalid MulticastDNSHostName. 131*ffe74184SMartin Algesten #[error("invalid mDNS HostName, must end with .local and can only contain a single '.'")] 132*ffe74184SMartin Algesten ErrInvalidMulticastDnshostName, 133*ffe74184SMartin Algesten 134*ffe74184SMartin Algesten /// Indicates Restart was called when Agent is in GatheringStateGathering. 135*ffe74184SMartin Algesten #[error("ICE Agent can not be restarted when gathering")] 136*ffe74184SMartin Algesten ErrRestartWhenGathering, 137*ffe74184SMartin Algesten 138*ffe74184SMartin Algesten /// Indicates a run operation was canceled by its individual done. 139*ffe74184SMartin Algesten #[error("run was canceled by done")] 140*ffe74184SMartin Algesten ErrRunCanceled, 141*ffe74184SMartin Algesten 142*ffe74184SMartin Algesten /// Initialized Indicates TCPMux is not initialized and that invalidTCPMux is used. 143*ffe74184SMartin Algesten #[error("TCPMux is not initialized")] 144*ffe74184SMartin Algesten ErrTcpMuxNotInitialized, 145*ffe74184SMartin Algesten 146*ffe74184SMartin Algesten /// Indicates we already have the connection with same remote addr. 147*ffe74184SMartin Algesten #[error("conn with same remote addr already exists")] 148*ffe74184SMartin Algesten ErrTcpRemoteAddrAlreadyExists, 149*ffe74184SMartin Algesten 150*ffe74184SMartin Algesten #[error("failed to send packet")] 151*ffe74184SMartin Algesten ErrSendPacket, 152*ffe74184SMartin Algesten #[error("attribute not long enough to be ICE candidate")] 153*ffe74184SMartin Algesten ErrAttributeTooShortIceCandidate, 154*ffe74184SMartin Algesten #[error("could not parse component")] 155*ffe74184SMartin Algesten ErrParseComponent, 156*ffe74184SMartin Algesten #[error("could not parse priority")] 157*ffe74184SMartin Algesten ErrParsePriority, 158*ffe74184SMartin Algesten #[error("could not parse port")] 159*ffe74184SMartin Algesten ErrParsePort, 160*ffe74184SMartin Algesten #[error("could not parse related addresses")] 161*ffe74184SMartin Algesten ErrParseRelatedAddr, 162*ffe74184SMartin Algesten #[error("could not parse type")] 163*ffe74184SMartin Algesten ErrParseType, 164*ffe74184SMartin Algesten #[error("unknown candidate type")] 165*ffe74184SMartin Algesten ErrUnknownCandidateType, 166*ffe74184SMartin Algesten #[error("failed to get XOR-MAPPED-ADDRESS response")] 167*ffe74184SMartin Algesten ErrGetXorMappedAddrResponse, 168*ffe74184SMartin Algesten #[error("connection with same remote address already exists")] 169*ffe74184SMartin Algesten ErrConnectionAddrAlreadyExist, 170*ffe74184SMartin Algesten #[error("error reading streaming packet")] 171*ffe74184SMartin Algesten ErrReadingStreamingPacket, 172*ffe74184SMartin Algesten #[error("error writing to")] 173*ffe74184SMartin Algesten ErrWriting, 174*ffe74184SMartin Algesten #[error("error closing connection")] 175*ffe74184SMartin Algesten ErrClosingConnection, 176*ffe74184SMartin Algesten #[error("unable to determine networkType")] 177*ffe74184SMartin Algesten ErrDetermineNetworkType, 178*ffe74184SMartin Algesten #[error("missing protocol scheme")] 179*ffe74184SMartin Algesten ErrMissingProtocolScheme, 180*ffe74184SMartin Algesten #[error("too many colons in address")] 181*ffe74184SMartin Algesten ErrTooManyColonsAddr, 182*ffe74184SMartin Algesten #[error("unexpected error trying to read")] 183*ffe74184SMartin Algesten ErrRead, 184*ffe74184SMartin Algesten #[error("unknown role")] 185*ffe74184SMartin Algesten ErrUnknownRole, 186*ffe74184SMartin Algesten #[error("username mismatch")] 187*ffe74184SMartin Algesten ErrMismatchUsername, 188*ffe74184SMartin Algesten #[error("the ICE conn can't write STUN messages")] 189*ffe74184SMartin Algesten ErrIceWriteStunMessage, 190*ffe74184SMartin Algesten #[error("invalid url")] 191*ffe74184SMartin Algesten ErrInvalidUrl, 192*ffe74184SMartin Algesten #[error("relative URL without a base")] 193*ffe74184SMartin Algesten ErrUrlParse, 194*ffe74184SMartin Algesten #[error("Candidate IP could not be found")] 195*ffe74184SMartin Algesten ErrCandidateIpNotFound, 196*ffe74184SMartin Algesten 197*ffe74184SMartin Algesten #[error("parse int: {0}")] 198*ffe74184SMartin Algesten ParseInt(#[from] ParseIntError), 199*ffe74184SMartin Algesten #[error("parse addr: {0}")] 200*ffe74184SMartin Algesten ParseIp(#[from] net::AddrParseError), 201*ffe74184SMartin Algesten #[error("{0}")] 202*ffe74184SMartin Algesten Io(#[source] IoError), 203*ffe74184SMartin Algesten #[error("{0}")] 204*ffe74184SMartin Algesten Util(#[from] util::Error), 205*ffe74184SMartin Algesten #[error("{0}")] 206*ffe74184SMartin Algesten Stun(#[from] stun::Error), 207*ffe74184SMartin Algesten #[error("{0}")] 208*ffe74184SMartin Algesten ParseUrl(#[from] url::ParseError), 209*ffe74184SMartin Algesten #[error("{0}")] 210*ffe74184SMartin Algesten Mdns(#[from] mdns::Error), 211*ffe74184SMartin Algesten #[error("{0}")] 212*ffe74184SMartin Algesten Turn(#[from] turn::Error), 213*ffe74184SMartin Algesten 214*ffe74184SMartin Algesten #[error("{0}")] 215*ffe74184SMartin Algesten Other(String), 216*ffe74184SMartin Algesten } 217*ffe74184SMartin Algesten 218*ffe74184SMartin Algesten #[derive(Debug, Error)] 219*ffe74184SMartin Algesten #[error("io error: {0}")] 220*ffe74184SMartin Algesten pub struct IoError(#[from] pub io::Error); 221*ffe74184SMartin Algesten 222*ffe74184SMartin Algesten // Workaround for wanting PartialEq for io::Error. 223*ffe74184SMartin Algesten impl PartialEq for IoError { eq(&self, other: &Self) -> bool224*ffe74184SMartin Algesten fn eq(&self, other: &Self) -> bool { 225*ffe74184SMartin Algesten self.0.kind() == other.0.kind() 226*ffe74184SMartin Algesten } 227*ffe74184SMartin Algesten } 228*ffe74184SMartin Algesten 229*ffe74184SMartin Algesten impl From<io::Error> for Error { from(e: io::Error) -> Self230*ffe74184SMartin Algesten fn from(e: io::Error) -> Self { 231*ffe74184SMartin Algesten Error::Io(IoError(e)) 232*ffe74184SMartin Algesten } 233*ffe74184SMartin Algesten } 234*ffe74184SMartin Algesten 235*ffe74184SMartin Algesten impl From<SystemTimeError> for Error { from(e: SystemTimeError) -> Self236*ffe74184SMartin Algesten fn from(e: SystemTimeError) -> Self { 237*ffe74184SMartin Algesten Error::Other(e.to_string()) 238*ffe74184SMartin Algesten } 239*ffe74184SMartin Algesten } 240