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