use std::{io, net::IpAddr};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum MctxError {
#[error("MCTX: invalid destination port")]
InvalidDestinationPort,
#[error("MCTX: group must be a multicast IPv4 or IPv6 address")]
InvalidMulticastGroup,
#[error("MCTX: invalid source port")]
InvalidSourcePort,
#[error("MCTX: invalid source address")]
InvalidSourceAddress,
#[error("MCTX: invalid interface address")]
InvalidInterfaceAddress,
#[error("MCTX: invalid IPv6 interface index")]
InvalidIpv6InterfaceIndex,
#[error("MCTX: invalid raw bind address")]
InvalidRawBindAddress,
#[error("MCTX: source address family must match multicast group family")]
SourceAddressFamilyMismatch,
#[error("MCTX: outgoing interface family must match multicast group family")]
OutgoingInterfaceFamilyMismatch,
#[error("MCTX: raw bind address family must match the raw publication family")]
RawBindAddressFamilyMismatch,
#[error(
"MCTX: IPv6 source address {source_addr} resolves to interface index {source_interface_index}, expected {outgoing_interface_index}"
)]
Ipv6SourceInterfaceMismatch {
source_addr: IpAddr,
source_interface_index: u32,
outgoing_interface_index: u32,
},
#[error(
"MCTX: IPv6 interface-local and link-local multicast destinations require an outgoing interface or source address"
)]
Ipv6ScopedMulticastRequiresInterface,
#[error("MCTX: failed to resolve IPv6 interface: {0}")]
InterfaceDiscoveryFailed(String),
#[error("MCTX: publication already exists")]
DuplicatePublication,
#[error("MCTX: publication not found")]
PublicationNotFound,
#[error("MCTX: failed to create UDP socket: {0}")]
SocketCreateFailed(io::Error),
#[error("MCTX: failed to set socket option: {0}")]
SocketOptionFailed(io::Error),
#[error("MCTX: failed to bind UDP socket: {0}")]
SocketBindFailed(io::Error),
#[error("MCTX: failed to connect UDP socket: {0}")]
SocketConnectFailed(io::Error),
#[error("MCTX: failed to read local address from socket: {0}")]
SocketLocalAddrFailed(io::Error),
#[error("MCTX: existing socket address family does not match the publication")]
ExistingSocketAddressFamilyMismatch,
#[error("MCTX: existing socket is bound to UDP port {actual}, expected {expected}")]
ExistingSocketPortMismatch { expected: u16, actual: u16 },
#[error("MCTX: existing socket is bound to local IP address {actual}, expected {expected}")]
ExistingSocketAddressMismatch { expected: IpAddr, actual: IpAddr },
#[error("MCTX: send failed: {0}")]
SendFailed(io::Error),
#[error("MCTX: raw packet transmit is unsupported: {0}")]
RawPacketTransmitUnsupported(String),
#[error("MCTX: failed to create raw transmit socket: {0}")]
RawSocketCreateFailed(io::Error),
#[error("MCTX: failed to bind raw transmit socket: {0}")]
RawSocketBindFailed(io::Error),
#[error("MCTX: raw send failed: {0}")]
RawSendFailed(io::Error),
#[error("MCTX: invalid raw IP datagram")]
InvalidRawIpDatagram,
#[error("MCTX: raw datagram destination must be multicast")]
InvalidRawMulticastDestination,
#[error(
"MCTX: raw datagram source address {datagram_source} does not match configured bind address {configured_bind_addr}"
)]
RawDatagramSourceMismatch {
datagram_source: IpAddr,
configured_bind_addr: IpAddr,
},
#[error("MCTX: raw packet transmit requires an explicit outgoing interface or bind address")]
RawInterfaceRequired,
#[error("MCTX: raw packet transmit does not support link type {0}")]
RawUnsupportedLinkType(String),
}
impl MctxError {
#[cfg(feature = "tokio")]
pub(crate) fn is_would_block(&self) -> bool {
matches!(
self,
Self::SendFailed(error) | Self::RawSendFailed(error)
if error.kind() == io::ErrorKind::WouldBlock
)
}
}