Skip to main content

mctx_core/
error.rs

1use std::{io, net::IpAddr};
2use thiserror::Error;
3
4/// Errors returned by the multicast sender core.
5#[derive(Debug, Error)]
6pub enum MctxError {
7    /// The configured destination port is invalid.
8    #[error("MCTX: invalid destination port")]
9    InvalidDestinationPort,
10
11    /// The configured group address is not a valid multicast IP address.
12    #[error("MCTX: group must be a multicast IPv4 or IPv6 address")]
13    InvalidMulticastGroup,
14
15    /// The configured source port is invalid.
16    #[error("MCTX: invalid source port")]
17    InvalidSourcePort,
18
19    /// The configured source IP address is invalid.
20    #[error("MCTX: invalid source address")]
21    InvalidSourceAddress,
22
23    /// The configured multicast interface selector is invalid.
24    #[error("MCTX: invalid interface address")]
25    InvalidInterfaceAddress,
26
27    /// The configured IPv6 interface index is invalid.
28    #[error("MCTX: invalid IPv6 interface index")]
29    InvalidIpv6InterfaceIndex,
30
31    /// The configured raw bind address is invalid.
32    #[error("MCTX: invalid raw bind address")]
33    InvalidRawBindAddress,
34
35    /// The configured source address does not match the group address family.
36    #[error("MCTX: source address family must match multicast group family")]
37    SourceAddressFamilyMismatch,
38
39    /// The configured outgoing interface does not match the group address family.
40    #[error("MCTX: outgoing interface family must match multicast group family")]
41    OutgoingInterfaceFamilyMismatch,
42
43    /// The configured raw bind address does not match the expected datagram family.
44    #[error("MCTX: raw bind address family must match the raw publication family")]
45    RawBindAddressFamilyMismatch,
46
47    /// The configured IPv6 source address and outgoing interface disagree about
48    /// which interface should be used.
49    #[error(
50        "MCTX: IPv6 source address {source_addr} resolves to interface index {source_interface_index}, expected {outgoing_interface_index}"
51    )]
52    Ipv6SourceInterfaceMismatch {
53        source_addr: IpAddr,
54        source_interface_index: u32,
55        outgoing_interface_index: u32,
56    },
57
58    /// A scoped IPv6 multicast destination needs a concrete interface index.
59    #[error(
60        "MCTX: IPv6 interface-local and link-local multicast destinations require an outgoing interface or source address"
61    )]
62    Ipv6ScopedMulticastRequiresInterface,
63
64    /// Resolving a local IPv6 address to its interface index failed.
65    #[error("MCTX: failed to resolve IPv6 interface: {0}")]
66    InterfaceDiscoveryFailed(String),
67
68    /// A publication with the same configuration already exists.
69    #[error("MCTX: publication already exists")]
70    DuplicatePublication,
71
72    /// No publication with the requested ID exists.
73    #[error("MCTX: publication not found")]
74    PublicationNotFound,
75
76    /// Creating the UDP socket failed.
77    #[error("MCTX: failed to create UDP socket: {0}")]
78    SocketCreateFailed(io::Error),
79
80    /// Setting a socket option failed.
81    #[error("MCTX: failed to set socket option: {0}")]
82    SocketOptionFailed(io::Error),
83
84    /// Binding the UDP socket failed.
85    #[error("MCTX: failed to bind UDP socket: {0}")]
86    SocketBindFailed(io::Error),
87
88    /// Connecting the UDP socket failed.
89    #[error("MCTX: failed to connect UDP socket: {0}")]
90    SocketConnectFailed(io::Error),
91
92    /// Reading the local address from a socket failed.
93    #[error("MCTX: failed to read local address from socket: {0}")]
94    SocketLocalAddrFailed(io::Error),
95
96    /// The provided existing socket does not match the configured IP family.
97    #[error("MCTX: existing socket address family does not match the publication")]
98    ExistingSocketAddressFamilyMismatch,
99
100    /// The provided existing socket is bound to a different UDP port than requested.
101    #[error("MCTX: existing socket is bound to UDP port {actual}, expected {expected}")]
102    ExistingSocketPortMismatch { expected: u16, actual: u16 },
103
104    /// The provided existing socket is bound to a different local IP address than requested.
105    #[error("MCTX: existing socket is bound to local IP address {actual}, expected {expected}")]
106    ExistingSocketAddressMismatch { expected: IpAddr, actual: IpAddr },
107
108    /// Sending a packet failed.
109    #[error("MCTX: send failed: {0}")]
110    SendFailed(io::Error),
111
112    /// Raw multicast packet transmit is not supported on the current platform or configuration.
113    #[error("MCTX: raw packet transmit is unsupported: {0}")]
114    RawPacketTransmitUnsupported(String),
115
116    /// Creating the raw transmit socket failed.
117    #[error("MCTX: failed to create raw transmit socket: {0}")]
118    RawSocketCreateFailed(io::Error),
119
120    /// Binding the raw transmit socket failed.
121    #[error("MCTX: failed to bind raw transmit socket: {0}")]
122    RawSocketBindFailed(io::Error),
123
124    /// Sending a raw IP datagram failed.
125    #[error("MCTX: raw send failed: {0}")]
126    RawSendFailed(io::Error),
127
128    /// The supplied raw datagram bytes are not a valid complete IPv4 or IPv6 datagram.
129    #[error("MCTX: invalid raw IP datagram")]
130    InvalidRawIpDatagram,
131
132    /// The supplied raw datagram does not target a multicast destination.
133    #[error("MCTX: raw datagram destination must be multicast")]
134    InvalidRawMulticastDestination,
135
136    /// The supplied raw datagram source conflicts with the configured bind address.
137    #[error(
138        "MCTX: raw datagram source address {datagram_source} does not match configured bind address {configured_bind_addr}"
139    )]
140    RawDatagramSourceMismatch {
141        datagram_source: IpAddr,
142        configured_bind_addr: IpAddr,
143    },
144
145    /// Raw packet transmit needs an explicit outgoing interface selection.
146    #[error("MCTX: raw packet transmit requires an explicit outgoing interface or bind address")]
147    RawInterfaceRequired,
148
149    /// Raw packet transmit is not implemented for the selected link type.
150    #[error("MCTX: raw packet transmit does not support link type {0}")]
151    RawUnsupportedLinkType(String),
152}
153
154impl MctxError {
155    #[cfg(feature = "tokio")]
156    pub(crate) fn is_would_block(&self) -> bool {
157        matches!(
158            self,
159            Self::SendFailed(error) | Self::RawSendFailed(error)
160                if error.kind() == io::ErrorKind::WouldBlock
161        )
162    }
163}