Skip to main content

mctx_core/raw/
publication.rs

1use crate::error::MctxError;
2use crate::raw::platform::{RawTransmitSocket, open_raw_transmit_socket, send_raw_ip_datagram};
3use crate::raw::{RawPublicationConfig, RawSendReport};
4
5/// Stable ID for one configured raw publication socket.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct RawPublicationId(pub u64);
8
9/// One ready-to-send raw multicast publication.
10#[derive(Debug)]
11pub struct RawPublication {
12    id: RawPublicationId,
13    config: RawPublicationConfig,
14    socket: RawTransmitSocket,
15}
16
17impl RawPublication {
18    /// Creates and configures a new raw publication socket.
19    pub fn new(id: RawPublicationId, config: RawPublicationConfig) -> Result<Self, MctxError> {
20        let socket = open_raw_transmit_socket(&config)?;
21
22        Ok(Self { id, config, socket })
23    }
24
25    /// Returns the raw publication ID.
26    pub fn id(&self) -> RawPublicationId {
27        self.id
28    }
29
30    /// Returns the configured raw publication parameters.
31    pub fn config(&self) -> &RawPublicationConfig {
32        &self.config
33    }
34
35    /// Sends one complete IP datagram through the selected raw backend.
36    ///
37    /// Link-layer backends preserve the supplied header. Host-stack IPv6
38    /// backends rebuild the base IPv6 header and only accept a matching local
39    /// source address.
40    pub fn send_raw(&self, ip_datagram: &[u8]) -> Result<RawSendReport, MctxError> {
41        send_raw_ip_datagram(&self.socket, self.id, &self.config, ip_datagram)
42    }
43}
44
45#[cfg(all(test, any(target_os = "linux", target_os = "macos")))]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn raw_ipv6_publication_accepts_explicit_loopback_override() {
51        let publication = RawPublication::new(
52            RawPublicationId(2),
53            RawPublicationConfig::ipv6()
54                .with_ipv6_interface_index(7)
55                .with_loopback(false),
56        )
57        .unwrap();
58
59        assert_eq!(publication.config().loopback, Some(false));
60    }
61}