1use std::{io, net::IpAddr};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
6pub enum MctxError {
7 #[error("MCTX: invalid destination port")]
9 InvalidDestinationPort,
10
11 #[error("MCTX: group must be a multicast IPv4 or IPv6 address")]
13 InvalidMulticastGroup,
14
15 #[error("MCTX: invalid source port")]
17 InvalidSourcePort,
18
19 #[error("MCTX: invalid source address")]
21 InvalidSourceAddress,
22
23 #[error("MCTX: invalid interface address")]
25 InvalidInterfaceAddress,
26
27 #[error("MCTX: invalid IPv6 interface index")]
29 InvalidIpv6InterfaceIndex,
30
31 #[error("MCTX: invalid raw bind address")]
33 InvalidRawBindAddress,
34
35 #[error("MCTX: source address family must match multicast group family")]
37 SourceAddressFamilyMismatch,
38
39 #[error("MCTX: outgoing interface family must match multicast group family")]
41 OutgoingInterfaceFamilyMismatch,
42
43 #[error("MCTX: raw bind address family must match the raw publication family")]
45 RawBindAddressFamilyMismatch,
46
47 #[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 #[error(
60 "MCTX: IPv6 interface-local and link-local multicast destinations require an outgoing interface or source address"
61 )]
62 Ipv6ScopedMulticastRequiresInterface,
63
64 #[error("MCTX: failed to resolve IPv6 interface: {0}")]
66 InterfaceDiscoveryFailed(String),
67
68 #[error("MCTX: publication already exists")]
70 DuplicatePublication,
71
72 #[error("MCTX: publication not found")]
74 PublicationNotFound,
75
76 #[error("MCTX: failed to create UDP socket: {0}")]
78 SocketCreateFailed(io::Error),
79
80 #[error("MCTX: failed to set socket option: {0}")]
82 SocketOptionFailed(io::Error),
83
84 #[error("MCTX: failed to bind UDP socket: {0}")]
86 SocketBindFailed(io::Error),
87
88 #[error("MCTX: failed to connect UDP socket: {0}")]
90 SocketConnectFailed(io::Error),
91
92 #[error("MCTX: failed to read local address from socket: {0}")]
94 SocketLocalAddrFailed(io::Error),
95
96 #[error("MCTX: existing socket address family does not match the publication")]
98 ExistingSocketAddressFamilyMismatch,
99
100 #[error("MCTX: existing socket is bound to UDP port {actual}, expected {expected}")]
102 ExistingSocketPortMismatch { expected: u16, actual: u16 },
103
104 #[error("MCTX: existing socket is bound to local IP address {actual}, expected {expected}")]
106 ExistingSocketAddressMismatch { expected: IpAddr, actual: IpAddr },
107
108 #[error("MCTX: send failed: {0}")]
110 SendFailed(io::Error),
111
112 #[error("MCTX: raw packet transmit is unsupported: {0}")]
114 RawPacketTransmitUnsupported(String),
115
116 #[error("MCTX: failed to create raw transmit socket: {0}")]
118 RawSocketCreateFailed(io::Error),
119
120 #[error("MCTX: failed to bind raw transmit socket: {0}")]
122 RawSocketBindFailed(io::Error),
123
124 #[error("MCTX: raw send failed: {0}")]
126 RawSendFailed(io::Error),
127
128 #[error("MCTX: invalid raw IP datagram")]
130 InvalidRawIpDatagram,
131
132 #[error("MCTX: raw datagram destination must be multicast")]
134 InvalidRawMulticastDestination,
135
136 #[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 #[error("MCTX: raw packet transmit requires an explicit outgoing interface or bind address")]
147 RawInterfaceRequired,
148
149 #[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}