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}