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}