sctp_rs/
connected_socket.rs

1//! A Connected SCTP Socket. This is similar to `TCPStream`.
2
3use tokio::io::unix::AsyncFd;
4
5use std::net::SocketAddr;
6use std::os::unix::io::RawFd;
7
8#[allow(unused)]
9use crate::internal::*;
10use crate::{
11    AssociationId, BindxFlags, ConnStatus, Event, NotificationOrData, SendData, SendInfo,
12    SubscribeEventAssocId,
13};
14
15/// A structure representing a Connected SCTP socket.
16///
17/// A Connected SCTP Socket is associated with one or more Peer associations (each of which is
18/// identified by an Association ID). A Connected SCTP Socket will be created by an
19/// [`Listener`][crate::Listener] when it calls an `accept` (in the case of One to One style
20/// sockets) or upon receiving a `SCTP_COMM_UP` event in `SCTP_ASSOC_CHANGE` notification.
21///
22/// It is also possible to [`peeloff`][crate::Listener::sctp_peeloff] a socket from One to Many
23/// listening socket and the peeled socket is an [`ConnectedSocket`].
24#[derive(Debug)]
25pub struct ConnectedSocket {
26    inner: AsyncFd<RawFd>,
27}
28
29impl ConnectedSocket {
30    /// Creates new [`ConnectedSocket`] from a [`RawFd`][std::os::unix::io::RawFd].
31    ///
32    /// TODO: Remove this from Public API
33    /// Although, this is available as public API as of now, likely the users are not required to
34    /// use this. Mostly [`accept`][`crate::Listener::accept`] (in the case of One to One
35    /// Socket to Association) or [`peeloff`][`crate::Listener::sctp_peeloff`] (in the case of
36    /// One to Many Association) would use this API to create new [`ConnectedSocket`].
37    pub fn from_rawfd(rawfd: RawFd) -> std::io::Result<Self> {
38        Ok(Self {
39            inner: AsyncFd::new(rawfd)?,
40        })
41    }
42
43    /// Perform a TCP like half close.
44    ///
45    /// Note: however that the semantics for TCP and SCTP half close are different. See section
46    /// 4.1.7 of RFC 6458 for details.
47    pub fn shutdown(&self, how: std::net::Shutdown) -> std::io::Result<()> {
48        shutdown_internal(&self.inner, how)
49    }
50
51    /// Bind to addresses on the given socket. See Section 9.1 RFC 6458.
52    ///
53    /// For the connected sockets, this feature is optional and hence will *always* return
54    /// `ENOTSUP(EOPNOTSUP)` error.
55    pub fn sctp_bindx(&self, _addrs: &[SocketAddr], _flags: BindxFlags) -> std::io::Result<()> {
56        Err(std::io::Error::from_raw_os_error(95))
57    }
58
59    /// Get Peer addresses for the association. See Section 9.3 RFC 6458.
60    pub fn sctp_getpaddrs(&self, assoc_id: AssociationId) -> std::io::Result<Vec<SocketAddr>> {
61        sctp_getpaddrs_internal(&self.inner, assoc_id)
62    }
63
64    /// Get Local addresses for the association. See section 9.5 RFC 6458.
65    pub fn sctp_getladdrs(&self, assoc_id: AssociationId) -> std::io::Result<Vec<SocketAddr>> {
66        sctp_getladdrs_internal(&self.inner, assoc_id)
67    }
68
69    /// Receive Data or Notification from the connected socket.
70    ///
71    /// The internal API used to receive the data is also the API used to receive notifications.
72    /// This function returns either the notification (which the user should have subscribed for)
73    /// or the data.
74    pub async fn sctp_recv(&self) -> std::io::Result<NotificationOrData> {
75        sctp_recvmsg_internal(&self.inner).await
76    }
77
78    /// Send Data and Anciliary data if any on the SCTP Socket.
79    ///
80    /// SCTP supports sending the actual SCTP message together with sending any anciliary data on
81    /// the SCTP association. The anciliary data is optional.
82    pub async fn sctp_send(&self, data: SendData) -> std::io::Result<()> {
83        sctp_sendmsg_internal(&self.inner, None, data).await
84    }
85
86    /// Subscribe to a given SCTP Event on the given socket. See section 6.2.1 of RFC6458.
87    ///
88    /// SCTP allows receiving notifications about the changes to SCTP associations etc from the
89    /// user space. For these notification events to be received, this API is used to subsribe for
90    /// the events while receiving the data on the SCTP Socket.
91    #[deprecated(since = "0.2.2", note = "use sctp_subscribe_events instead.")]
92    pub fn sctp_subscribe_event(
93        &self,
94        event: Event,
95        assoc_id: SubscribeEventAssocId,
96    ) -> std::io::Result<()> {
97        sctp_subscribe_event_internal(&self.inner, event, assoc_id, true)
98    }
99
100    /// Unsubscribe from a given SCTP Event on the given socket. See section 6.2.1 of RFC6458.
101    ///
102    /// See [`sctp_subscribe_event`][`Self::sctp_subscribe_event`] for further details.
103    #[deprecated(since = "0.2.2", note = "use sctp_unsubscribe_events instead.")]
104    pub fn sctp_unsubscribe_event(
105        &self,
106        event: Event,
107        assoc_id: SubscribeEventAssocId,
108    ) -> std::io::Result<()> {
109        sctp_subscribe_event_internal(&self.inner, event, assoc_id, false)
110    }
111
112    /// Subscribe to SCTP Events. See section 6.2.1 of RFC6458.
113    ///
114    /// SCTP allows receiving notifications about the changes to SCTP associations etc from the
115    /// user space. For these notification events to be received, this API is used to subsribe for
116    /// the events while receiving the data on the SCTP Socket.
117    pub fn sctp_subscribe_events(
118        &self,
119        events: &[Event],
120        assoc_id: SubscribeEventAssocId,
121    ) -> std::io::Result<()> {
122        let mut failures = vec![];
123        for ev in events {
124            let result = sctp_subscribe_event_internal(&self.inner, ev.clone(), assoc_id, true);
125            if result.is_err() {
126                failures.push(result.err().unwrap());
127            }
128        }
129
130        if failures.is_empty() {
131            Ok(())
132        } else {
133            Err(std::io::Error::new(
134                std::io::ErrorKind::Other,
135                format!("{:?}", failures),
136            ))
137        }
138    }
139
140    /// Unsubscribe from a given SCTP Event on the given socket. See section 6.2.1 of RFC6458.
141    ///
142    /// See [`sctp_subscribe_events`][`Self::sctp_subscribe_events`] for further details.
143    pub fn sctp_unsubscribe_events(
144        &self,
145        events: &[Event],
146        assoc_id: SubscribeEventAssocId,
147    ) -> std::io::Result<()> {
148        let mut failures = vec![];
149        for ev in events {
150            let result = sctp_subscribe_event_internal(&self.inner, ev.clone(), assoc_id, false);
151            if result.is_err() {
152                failures.push(result.err().unwrap());
153            }
154        }
155
156        if failures.is_empty() {
157            Ok(())
158        } else {
159            Err(std::io::Error::new(
160                std::io::ErrorKind::Other,
161                format!("{:?}", failures),
162            ))
163        }
164    }
165
166    /// Request to receive `RcvInfo` ancillary data.
167    ///
168    /// SCTP allows receiving ancillary data about the curent data received on the given socket.
169    /// This API is used to obtain receive side additional info when the data is to be received.
170    pub fn sctp_request_rcvinfo(&self, on: bool) -> std::io::Result<()> {
171        request_rcvinfo_internal(&self.inner, on)
172    }
173
174    /// Request to receive `NxtInfo` ancillary data.
175    ///
176    /// SCTP allows receiving ancillary data about the curent data received on the given socket.
177    /// This API is used to obtain information about the next datagram that will be received.
178    pub fn sctp_request_nxtinfo(&self, on: bool) -> std::io::Result<()> {
179        request_nxtinfo_internal(&self.inner, on)
180    }
181
182    /// Get the status of the connection associated with the association ID.
183    pub fn sctp_get_status(&self, assoc_id: AssociationId) -> std::io::Result<ConnStatus> {
184        sctp_get_status_internal(&self.inner, assoc_id)
185    }
186
187    /// Set Default `SendInfo` values for this socket.
188    ///
189    /// In the [`sctp_send`] API, an optional `SendInfo` is present, which can be used to specify the
190    /// ancillary data along with the payload. Instead, a sender can chose to use this API to set
191    /// the default `SendInfo` to be used while sending the data for this 'connected' socket.
192    /// Note: This API is provided only for the [`ConnectedSocket`].
193    pub fn sctp_set_default_sendinfo(&self, sendinfo: SendInfo) -> std::io::Result<()> {
194        sctp_set_default_sendinfo_internal(&self.inner, sendinfo)
195    }
196}
197
198impl Drop for ConnectedSocket {
199    // Drop for `ConnectedSocket`. We close the `inner` RawFd
200    fn drop(&mut self) {
201        close_internal(&self.inner);
202    }
203}