sctp_rs/
listener.rs

1//! Listening SCTP Socket
2
3use std::net::SocketAddr;
4use std::os::unix::io::RawFd;
5
6use tokio::io::unix::AsyncFd;
7
8#[allow(unused)]
9use crate::internal::*;
10use crate::{
11    types::AssociationId, BindxFlags, ConnStatus, ConnectedSocket, Event, NotificationOrData,
12    SendData, SubscribeEventAssocId,
13};
14
15/// A structure representing a socket that is listening for incoming SCTP Connections.
16///
17/// This structure is created by an [`Socket`][crate::Socket] when it is bound to local address(es)
18/// and is waiting for incoming connections by calling the `listen` on the socket. The original
19/// [`Socket`][crate::Socket] is consumed when this structure is created. See
20/// [`Socket::listen`][crate::Socket::listen] for more details.
21pub struct Listener {
22    inner: AsyncFd<RawFd>,
23}
24
25impl Listener {
26    /// Accept on a given socket (valid only for `OneToOne` type sockets).
27    pub async fn accept(&self) -> std::io::Result<(ConnectedSocket, SocketAddr)> {
28        accept_internal(&self.inner).await
29    }
30
31    /// Shutdown on the socket
32    pub fn shutdown(&self, how: std::net::Shutdown) -> std::io::Result<()> {
33        shutdown_internal(&self.inner, how)
34    }
35
36    /// Binds to one or more local addresses. See: Section 9.1 RFC 6458
37    ///
38    /// It is possible to call `sctp_bindx` on an already 'bound' (that is 'listen'ing socket.)
39    pub fn sctp_bindx(&self, addrs: &[SocketAddr], flags: BindxFlags) -> std::io::Result<()> {
40        sctp_bindx_internal(&self.inner, addrs, flags)
41    }
42
43    /// Peels off a connected SCTP association from the listening socket. See: Section 9.2 RFC 6458
44    ///
45    /// This call is successful only for UDP style one to many sockets. This is like
46    /// `[Listener::accept`] where peeled off socket behaves like a stand alone
47    /// one-to-one socket.
48    pub fn sctp_peeloff(&self, assoc_id: AssociationId) -> std::io::Result<ConnectedSocket> {
49        sctp_peeloff_internal(&self.inner, assoc_id)
50    }
51
52    /// Get Peer Address(es) for the given Association ID. See: Section 9.3 RFC 6458
53    ///
54    /// This function is supported on the [`Listener`] because in the case of One to Many
55    /// associations that are not peeled off, we are performing IO operations on the listening
56    /// socket itself.
57    pub fn sctp_getpaddrs(&self, assoc_id: AssociationId) -> std::io::Result<Vec<SocketAddr>> {
58        sctp_getpaddrs_internal(&self.inner, assoc_id)
59    }
60
61    /// Get's the Local Addresses for the association. See: Section 9.4 RFC 6458
62    pub fn sctp_getladdrs(&self, assoc_id: AssociationId) -> std::io::Result<Vec<SocketAddr>> {
63        sctp_getladdrs_internal(&self.inner, assoc_id)
64    }
65
66    /// Receive Data or Notification from the listening socket.
67    ///
68    /// In the case of One-to-many sockets, it is possible to receive on the listening socket,
69    /// without explicitly 'accept'ing or 'peeling off' the socket. The internal API used to
70    /// receive the data is also the API used to receive notifications. This function returns
71    /// either the notification (which the user should have subscribed for) or the data.
72    pub async fn sctp_recv(&self) -> std::io::Result<NotificationOrData> {
73        sctp_recvmsg_internal(&self.inner).await
74    }
75
76    /// Send Data and Anciliary data if any on the SCTP Socket.
77    ///
78    /// SCTP supports sending the actual SCTP message together with sending any anciliary data on
79    /// the SCTP association. The anciliary data is optional.
80    pub async fn sctp_send(&self, to: SocketAddr, data: SendData) -> std::io::Result<()> {
81        sctp_sendmsg_internal(&self.inner, Some(to), data).await
82    }
83
84    /// Subscribe to a given SCTP Event on the given socket. See section 6.2.1 of RFC6458.
85    ///
86    /// SCTP allows receiving notifications about the changes to SCTP associations etc from the
87    /// user space. For these notification events to be received, this API is used to subsribe for
88    /// the events while receiving the data on the SCTP Socket.
89    #[deprecated(since = "0.2.2", note = "use sctp_subscribe_events instead.")]
90    pub fn sctp_subscribe_event(
91        &self,
92        event: Event,
93        assoc_id: SubscribeEventAssocId,
94    ) -> std::io::Result<()> {
95        sctp_subscribe_event_internal(&self.inner, event, assoc_id, true)
96    }
97
98    /// Unsubscribe from a given SCTP Event on the given socket. See section 6.2.1 of RFC6458.
99    ///
100    /// See [`sctp_subscribe_event`][`Self::sctp_subscribe_event`] for further details.
101    #[deprecated(since = "0.2.2", note = "use sctp_unsubscribe_events instead.")]
102    pub fn sctp_unsubscribe_event(
103        &self,
104        event: Event,
105        assoc_id: SubscribeEventAssocId,
106    ) -> std::io::Result<()> {
107        sctp_subscribe_event_internal(&self.inner, event, assoc_id, false)
108    }
109
110    /// Subscribe to SCTP Events. See section 6.2.1 of RFC6458.
111    ///
112    /// SCTP allows receiving notifications about the changes to SCTP associations etc from the
113    /// user space. For these notification events to be received, this API is used to subsribe for
114    /// the events while receiving the data on the SCTP Socket.
115    pub fn sctp_subscribe_events(
116        &self,
117        events: &[Event],
118        assoc_id: SubscribeEventAssocId,
119    ) -> std::io::Result<()> {
120        let mut failures = vec![];
121        for ev in events {
122            let result = sctp_subscribe_event_internal(&self.inner, ev.clone(), assoc_id, true);
123            if result.is_err() {
124                failures.push(result.err().unwrap());
125            }
126        }
127
128        if failures.is_empty() {
129            Ok(())
130        } else {
131            Err(std::io::Error::new(
132                std::io::ErrorKind::Other,
133                format!("{:?}", failures),
134            ))
135        }
136    }
137
138    /// Unsubscribe from a given SCTP Event on the given socket. See section 6.2.1 of RFC6458.
139    ///
140    /// See [`sctp_subscribe_events`][`Self::sctp_subscribe_events`] for further details.
141    pub fn sctp_unsubscribe_events(
142        &self,
143        events: &[Event],
144        assoc_id: SubscribeEventAssocId,
145    ) -> std::io::Result<()> {
146        let mut failures = vec![];
147        for ev in events {
148            let result = sctp_subscribe_event_internal(&self.inner, ev.clone(), assoc_id, false);
149            if result.is_err() {
150                failures.push(result.err().unwrap());
151            }
152        }
153
154        if failures.is_empty() {
155            Ok(())
156        } else {
157            Err(std::io::Error::new(
158                std::io::ErrorKind::Other,
159                format!("{:?}", failures),
160            ))
161        }
162    }
163
164    /// Setup parameters for a new association.
165    ///
166    /// To specify custom parameters for a new association this API is used.
167    pub fn sctp_setup_init_params(
168        &self,
169        ostreams: u16,
170        istreams: u16,
171        retries: u16,
172        timeout: u16,
173    ) -> std::io::Result<()> {
174        sctp_setup_init_params_internal(&self.inner, ostreams, istreams, retries, timeout)
175    }
176
177    /// Request to receive `RcvInfo` ancillary data.
178    ///
179    /// SCTP allows receiving ancillary data about the curent data received on the given socket.
180    /// This API is used to obtain receive side additional info when the data is to be received.
181    pub fn sctp_request_rcvinfo(&self, on: bool) -> std::io::Result<()> {
182        request_rcvinfo_internal(&self.inner, on)
183    }
184
185    /// Request to receive `NxtInfo` ancillary data.
186    ///
187    /// SCTP allows receiving ancillary data about the curent data received on the given socket.
188    /// This API is used to obtain information about the next datagram that will be received.
189    pub fn sctp_request_nxtinfo(&self, on: bool) -> std::io::Result<()> {
190        request_nxtinfo_internal(&self.inner, on)
191    }
192
193    /// Get the status of the connection associated with the association ID.
194    pub fn sctp_get_status(&self, assoc_id: AssociationId) -> std::io::Result<ConnStatus> {
195        sctp_get_status_internal(&self.inner, assoc_id)
196    }
197
198    // functions not part of public APIs
199    pub(crate) fn from_rawfd(fd: RawFd) -> std::io::Result<Self> {
200        Ok(Self {
201            inner: AsyncFd::new(fd)?,
202        })
203    }
204}
205
206impl Drop for Listener {
207    // Drop for `Listener`. We close the `inner` RawFd
208    fn drop(&mut self) {
209        close_internal(&self.inner);
210    }
211}