use crate::{
sock::{self, OwnedFd},
sys::{
bt_power, bt_security, sockaddr_l2, BTPROTO_L2CAP, BT_MODE, BT_PHY, BT_POWER, BT_POWER_FORCE_ACTIVE_OFF,
BT_POWER_FORCE_ACTIVE_ON, BT_RCVMTU, BT_SECURITY, BT_SECURITY_FIPS, BT_SECURITY_HIGH, BT_SECURITY_LOW,
BT_SECURITY_MEDIUM, BT_SECURITY_SDP, BT_SNDMTU, L2CAP_CONNINFO, L2CAP_LM, L2CAP_OPTIONS, SOL_L2CAP,
},
Address, AddressType,
};
use futures::ready;
use libc::{
AF_BLUETOOTH, EAGAIN, EINPROGRESS, MSG_PEEK, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM, SOCK_SEQPACKET,
SOCK_STREAM, SOL_BLUETOOTH, SOL_SOCKET, SO_ERROR, SO_RCVBUF, TIOCINQ, TIOCOUTQ,
};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
use std::{
convert::{TryFrom, TryInto},
fmt,
io::{Error, ErrorKind, Result},
marker::PhantomData,
mem::ManuallyDrop,
net::Shutdown,
os::{
raw::c_int,
unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
},
pin::Pin,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
task::{Context, Poll},
};
use tokio::io::{unix::AsyncFd, AsyncRead, AsyncWrite, ReadBuf};
pub use crate::sys::{l2cap_conninfo as ConnInfo, l2cap_options as Opts};
pub mod link_mode {
pub use crate::sys::{
L2CAP_LM_AUTH as AUTH, L2CAP_LM_ENCRYPT as ENCRYPT, L2CAP_LM_FIPS as FIPS, L2CAP_LM_MASTER as MASTER,
L2CAP_LM_RELIABLE as RELIABLE, L2CAP_LM_SECURE as SECURE, L2CAP_LM_TRUSTED as TRUSTED,
};
}
pub mod phy {
pub use crate::sys::{
BR1M1SLOT, BR1M3SLOT, BR1M5SLOT, EDR2M1SLOT, EDR2M3SLOT, EDR2M5SLOT, EDR3M1SLOT, EDR3M3SLOT, EDR3M5SLOT,
LE1MRX, LE1MTX, LE2MRX, LE2MTX, LECODEDRX, LECODEDTX,
};
}
pub const PSM_BR_EDR_DYN_START: u16 = 0x1001;
pub const PSM_LE_DYN_START: u16 = 0x80;
pub const PSM_LE_MAX: u16 = 0xff;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SocketAddr {
pub addr: Address,
pub addr_type: AddressType,
pub psm: u16,
pub cid: u16,
}
impl SocketAddr {
pub const fn new(addr: Address, addr_type: AddressType, psm: u16) -> Self {
Self { addr, addr_type, psm, cid: 0 }
}
pub const fn any_br_edr() -> Self {
Self { addr: Address::any(), addr_type: AddressType::BrEdr, psm: 0, cid: 0 }
}
pub const fn any_le() -> Self {
Self { addr: Address::any(), addr_type: AddressType::LePublic, psm: 0, cid: 0 }
}
}
impl sock::SysSockAddr for SocketAddr {
type SysSockAddr = sockaddr_l2;
fn into_sys_sock_addr(self) -> Self::SysSockAddr {
sockaddr_l2 {
l2_family: AF_BLUETOOTH as _,
l2_psm: self.psm.to_le(),
l2_cid: self.cid.to_le(),
l2_bdaddr: self.addr.into(),
l2_bdaddr_type: self.addr_type as _,
}
}
fn try_from_sys_sock_addr(saddr: Self::SysSockAddr) -> Result<Self> {
if saddr.l2_family != AF_BLUETOOTH as _ {
return Err(Error::new(ErrorKind::InvalidInput, "sockaddr_l2::l2_family is not AF_BLUETOOTH"));
}
Ok(Self {
addr: Address::from(saddr.l2_bdaddr),
addr_type: AddressType::from_u8(saddr.l2_bdaddr_type)
.ok_or_else(|| Error::new(ErrorKind::InvalidInput, "invalid sockaddr_l2::l2_bdaddr_type"))?,
psm: u16::from_le(saddr.l2_psm),
cid: u16::from_le(saddr.l2_cid),
})
}
}
fn any_bind_addr(addr: &SocketAddr) -> SocketAddr {
match addr.addr_type {
AddressType::BrEdr => SocketAddr::any_br_edr(),
AddressType::LePublic | AddressType::LeRandom => SocketAddr::any_le(),
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, FromPrimitive, ToPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SecurityLevel {
Sdp = BT_SECURITY_SDP as _,
Low = BT_SECURITY_LOW as _,
Medium = BT_SECURITY_MEDIUM as _,
High = BT_SECURITY_HIGH as _,
Fips = BT_SECURITY_FIPS as _,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Security {
pub level: SecurityLevel,
pub key_size: u8,
}
impl From<Security> for bt_security {
fn from(s: Security) -> Self {
bt_security { level: s.level as _, key_size: s.key_size }
}
}
impl TryFrom<bt_security> for Security {
type Error = Error;
fn try_from(value: bt_security) -> Result<Self> {
Ok(Self {
level: SecurityLevel::from_u8(value.level)
.ok_or_else(|| Error::new(ErrorKind::InvalidInput, "invalid bt_security::level"))?,
key_size: value.key_size,
})
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, FromPrimitive, ToPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FlowControl {
Basic = 0x00,
Ertm = 0x01,
Streaming = 0x02,
Le = 0x03,
Extended = 0x04,
}
pub struct Socket<Type> {
fd: AsyncFd<OwnedFd>,
_type: PhantomData<Type>,
}
impl<Type> fmt::Debug for Socket<Type> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Socket").field("fd", &self.fd.as_raw_fd()).finish()
}
}
impl<Type> Socket<Type> {
pub fn bind(&self, sa: SocketAddr) -> Result<()> {
sock::bind(self.fd.get_ref(), sa)
}
pub fn local_addr(&self) -> Result<SocketAddr> {
sock::getsockname(self.fd.get_ref())
}
fn peer_addr_priv(&self) -> Result<SocketAddr> {
sock::getpeername(self.fd.get_ref())
}
pub fn security(&self) -> Result<Security> {
let bts: bt_security = sock::getsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_SECURITY)?;
Security::try_from(bts)
}
pub fn set_security(&self, security: Security) -> Result<()> {
let bts: bt_security = security.into();
sock::setsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_SECURITY, &bts)
}
pub fn is_power_forced_active(&self) -> Result<bool> {
let value: bt_power = sock::getsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_POWER)?;
Ok(value.force_active == BT_POWER_FORCE_ACTIVE_ON as _)
}
pub fn set_power_forced_active(&self, power_forced_active: bool) -> Result<()> {
let value = bt_power {
force_active: if power_forced_active { BT_POWER_FORCE_ACTIVE_ON } else { BT_POWER_FORCE_ACTIVE_OFF }
as _,
};
sock::setsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_POWER, &value)
}
pub fn send_mtu(&self) -> Result<u16> {
match self.local_addr()?.addr_type {
AddressType::BrEdr => Ok(self.l2cap_opts()?.omtu),
_ => sock::getsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_SNDMTU),
}
}
pub fn recv_mtu(&self) -> Result<u16> {
match self.local_addr()?.addr_type {
AddressType::BrEdr => Ok(self.l2cap_opts()?.imtu),
_ => sock::getsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_RCVMTU),
}
}
pub fn set_recv_mtu(&self, recv_mtu: u16) -> Result<()> {
match self.local_addr()?.addr_type {
AddressType::BrEdr => {
let mut opts = self.l2cap_opts()?;
opts.imtu = recv_mtu;
self.set_l2cap_opts(&opts)
}
_ => sock::setsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_RCVMTU, &recv_mtu),
}
}
pub fn flow_control(&self) -> Result<FlowControl> {
let value: u8 = sock::getsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_MODE)?;
FlowControl::from_u8(value)
.ok_or_else(|| Error::new(ErrorKind::InvalidInput, "invalid flow control mode"))
}
pub fn set_flow_control(&self, flow_control: FlowControl) -> Result<()> {
let value = flow_control as u8;
sock::setsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_MODE, &value)
}
pub fn recv_buffer(&self) -> Result<i32> {
sock::getsockopt(self.fd.get_ref(), SOL_SOCKET, SO_RCVBUF)
}
pub fn set_recv_buffer(&self, recv_buffer: i32) -> Result<()> {
sock::setsockopt(self.fd.get_ref(), SOL_SOCKET, SO_RCVBUF, &recv_buffer)
}
pub fn l2cap_opts(&self) -> Result<Opts> {
sock::getsockopt(self.fd.get_ref(), SOL_L2CAP, L2CAP_OPTIONS)
}
pub fn set_l2cap_opts(&self, l2cap_opts: &Opts) -> Result<()> {
sock::setsockopt(self.fd.get_ref(), SOL_L2CAP, L2CAP_OPTIONS, l2cap_opts)
}
pub fn link_mode(&self) -> Result<i32> {
sock::getsockopt(self.fd.get_ref(), SOL_L2CAP, L2CAP_LM)
}
pub fn set_link_mode(&self, link_mode: i32) -> Result<()> {
sock::setsockopt(self.fd.get_ref(), SOL_L2CAP, L2CAP_LM, &link_mode)
}
pub fn conn_info(&self) -> Result<ConnInfo> {
sock::getsockopt(self.fd.get_ref(), SOL_L2CAP, L2CAP_CONNINFO)
}
pub fn phy(&self) -> Result<i32> {
sock::getsockopt(self.fd.get_ref(), SOL_BLUETOOTH, BT_PHY)
}
pub fn input_buffer(&self) -> Result<u32> {
let value: c_int = sock::ioctl_read(self.fd.get_ref(), TIOCINQ)?;
Ok(value as _)
}
pub fn output_buffer(&self) -> Result<u32> {
let value: c_int = sock::ioctl_read(self.fd.get_ref(), TIOCOUTQ)?;
Ok(value as _)
}
pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> {
Ok(Self { fd: AsyncFd::new(OwnedFd::new(fd))?, _type: PhantomData })
}
fn from_owned_fd(fd: OwnedFd) -> Result<Self> {
Ok(Self { fd: AsyncFd::new(fd)?, _type: PhantomData })
}
sock_priv!();
}
impl<Type> AsRawFd for Socket<Type> {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
impl<Type> IntoRawFd for Socket<Type> {
fn into_raw_fd(self) -> RawFd {
self.fd.into_inner().into_raw_fd()
}
}
impl<Type> FromRawFd for Socket<Type> {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_raw_fd(fd).expect("from_raw_fd failed")
}
}
impl Socket<Stream> {
pub fn new_stream() -> Result<Socket<Stream>> {
Ok(Self {
fd: AsyncFd::new(sock::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP)?)?,
_type: PhantomData,
})
}
pub fn listen(self, backlog: u32) -> Result<StreamListener> {
sock::listen(
self.fd.get_ref(),
backlog.try_into().map_err(|_| Error::new(ErrorKind::InvalidInput, "invalid backlog"))?,
)?;
Ok(StreamListener { socket: self })
}
pub async fn connect(self, sa: SocketAddr) -> Result<Stream> {
self.connect_priv(sa).await?;
Stream::from_socket(self)
}
}
impl Socket<SeqPacket> {
pub fn new_seq_packet() -> Result<Socket<SeqPacket>> {
Ok(Self {
fd: AsyncFd::new(sock::socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)?)?,
_type: PhantomData,
})
}
pub fn listen(self, backlog: u32) -> Result<SeqPacketListener> {
sock::listen(
self.fd.get_ref(),
backlog.try_into().map_err(|_| Error::new(ErrorKind::InvalidInput, "invalid backlog"))?,
)?;
Ok(SeqPacketListener { socket: self })
}
pub async fn connect(self, sa: SocketAddr) -> Result<SeqPacket> {
self.connect_priv(sa).await?;
Ok(SeqPacket { socket: self })
}
}
impl Socket<Datagram> {
pub fn new_datagram() -> Result<Socket<Datagram>> {
Ok(Self { fd: AsyncFd::new(sock::socket(AF_BLUETOOTH, SOCK_DGRAM, BTPROTO_L2CAP)?)?, _type: PhantomData })
}
pub fn into_datagram(self) -> Datagram {
Datagram { socket: self }
}
}
#[derive(Debug)]
pub struct StreamListener {
socket: Socket<Stream>,
}
impl StreamListener {
pub async fn bind(sa: SocketAddr) -> Result<Self> {
let socket = Socket::<Stream>::new_stream()?;
socket.bind(sa)?;
socket.listen(1)
}
pub async fn accept(&self) -> Result<(Stream, SocketAddr)> {
let (socket, sa) = self.socket.accept_priv().await?;
Ok((Stream::from_socket(socket)?, sa))
}
pub fn poll_accept(&self, cx: &mut Context) -> Poll<Result<(Stream, SocketAddr)>> {
let (socket, sa) = ready!(self.socket.poll_accept_priv(cx))?;
Poll::Ready(Ok((Stream::from_socket(socket)?, sa)))
}
pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> {
Ok(Self { socket: Socket::from_raw_fd(fd)? })
}
}
impl AsRef<Socket<Stream>> for StreamListener {
fn as_ref(&self) -> &Socket<Stream> {
&self.socket
}
}
impl AsRawFd for StreamListener {
fn as_raw_fd(&self) -> RawFd {
self.socket.as_raw_fd()
}
}
impl FromRawFd for StreamListener {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_raw_fd(fd).expect("from_raw_fd failed")
}
}
#[derive(Debug)]
pub struct Stream {
socket: Socket<Stream>,
send_mtu: AtomicUsize,
}
impl Stream {
fn from_socket(socket: Socket<Stream>) -> Result<Self> {
Ok(Self { socket, send_mtu: 0.into() })
}
pub async fn connect(addr: SocketAddr) -> Result<Self> {
let socket = Socket::<Stream>::new_stream()?;
socket.bind(any_bind_addr(&addr))?;
socket.connect(addr).await
}
pub fn peer_addr(&self) -> Result<SocketAddr> {
self.socket.peer_addr_priv()
}
pub async fn peek(&self, buf: &mut [u8]) -> Result<usize> {
self.socket.peek_priv(buf).await
}
pub fn poll_peek(&self, cx: &mut Context, buf: &mut ReadBuf) -> Poll<Result<usize>> {
self.socket.poll_peek_priv(cx, buf)
}
#[allow(clippy::needless_lifetimes)]
pub fn split<'a>(&'a mut self) -> (stream::ReadHalf<'a>, stream::WriteHalf<'a>) {
(stream::ReadHalf(self), stream::WriteHalf(self))
}
pub fn into_split(self) -> (stream::OwnedReadHalf, stream::OwnedWriteHalf) {
let stream = Arc::new(self);
let r = stream::OwnedReadHalf {
stream: ManuallyDrop::new(stream.clone()),
shutdown_on_drop: true,
drop: true,
};
let w = stream::OwnedWriteHalf { stream, shutdown_on_drop: true };
(r, w)
}
fn poll_write_priv(&self, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize>> {
let send_mtu = {
match self.send_mtu.load(Ordering::Acquire) {
0 => match self.socket.send_mtu() {
Ok(mtu) => {
let mtu = mtu.into();
log::trace!("Obtained send MTU {}", mtu);
self.send_mtu.store(mtu, Ordering::Release);
mtu
}
Err(_) => {
log::trace!("Send MTU not yet available, assuming 16");
16
}
},
mtu => mtu,
}
};
let max_len = buf.len().min(send_mtu);
let buf = &buf[..max_len];
self.socket.poll_send_priv(cx, buf)
}
pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> {
Self::from_socket(Socket::from_raw_fd(fd)?)
}
}
impl AsRef<Socket<Stream>> for Stream {
fn as_ref(&self) -> &Socket<Stream> {
&self.socket
}
}
impl AsRawFd for Stream {
fn as_raw_fd(&self) -> RawFd {
self.socket.as_raw_fd()
}
}
impl FromRawFd for Stream {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_raw_fd(fd).expect("from_raw_fd failed")
}
}
impl AsyncRead for Stream {
fn poll_read(self: Pin<&mut Self>, cx: &mut Context, buf: &mut ReadBuf) -> Poll<Result<()>> {
self.socket.poll_recv_priv(cx, buf)
}
}
impl AsyncWrite for Stream {
fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize>> {
self.poll_write_priv(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<()>> {
self.socket.poll_flush_priv(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<()>> {
self.socket.poll_shutdown_priv(cx, Shutdown::Write)
}
}
#[allow(clippy::duplicate_mod)]
#[path = "stream_util.rs"]
pub mod stream;
#[derive(Debug)]
pub struct SeqPacketListener {
socket: Socket<SeqPacket>,
}
impl SeqPacketListener {
pub async fn bind(sa: SocketAddr) -> Result<Self> {
let socket = Socket::<SeqPacket>::new_seq_packet()?;
socket.bind(sa)?;
socket.listen(1)
}
pub async fn accept(&self) -> Result<(SeqPacket, SocketAddr)> {
let (socket, sa) = self.socket.accept_priv().await?;
Ok((SeqPacket { socket }, sa))
}
pub fn poll_accept(&self, cx: &mut Context) -> Poll<Result<(SeqPacket, SocketAddr)>> {
let (socket, sa) = ready!(self.socket.poll_accept_priv(cx))?;
Poll::Ready(Ok((SeqPacket { socket }, sa)))
}
pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> {
Ok(Self { socket: Socket::from_raw_fd(fd)? })
}
}
impl AsRef<Socket<SeqPacket>> for SeqPacketListener {
fn as_ref(&self) -> &Socket<SeqPacket> {
&self.socket
}
}
impl AsRawFd for SeqPacketListener {
fn as_raw_fd(&self) -> RawFd {
self.socket.as_raw_fd()
}
}
impl FromRawFd for SeqPacketListener {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_raw_fd(fd).expect("from_raw_fd failed")
}
}
#[derive(Debug)]
pub struct SeqPacket {
socket: Socket<SeqPacket>,
}
impl SeqPacket {
pub async fn connect(addr: SocketAddr) -> Result<Self> {
let socket = Socket::<SeqPacket>::new_seq_packet()?;
socket.bind(any_bind_addr(&addr))?;
socket.connect(addr).await
}
pub fn peer_addr(&self) -> Result<SocketAddr> {
self.socket.peer_addr_priv()
}
pub async fn send(&self, buf: &[u8]) -> Result<usize> {
self.socket.send_priv(buf).await
}
pub fn poll_send(&self, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize>> {
self.socket.poll_send_priv(cx, buf)
}
pub async fn recv(&self, buf: &mut [u8]) -> Result<usize> {
self.socket.recv_priv(buf).await
}
pub fn poll_recv(&self, cx: &mut Context, buf: &mut ReadBuf) -> Poll<Result<()>> {
self.socket.poll_recv_priv(cx, buf)
}
pub fn shutdown(&self, how: Shutdown) -> Result<()> {
self.socket.shutdown_priv(how)
}
pub fn send_mtu(&self) -> Result<usize> {
self.socket.send_mtu().map(|v| v.into())
}
pub fn recv_mtu(&self) -> Result<usize> {
self.socket.recv_mtu().map(|v| v.into())
}
pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> {
Ok(Self { socket: Socket::from_raw_fd(fd)? })
}
}
impl AsRef<Socket<SeqPacket>> for SeqPacket {
fn as_ref(&self) -> &Socket<SeqPacket> {
&self.socket
}
}
impl AsRawFd for SeqPacket {
fn as_raw_fd(&self) -> RawFd {
self.socket.as_raw_fd()
}
}
impl FromRawFd for SeqPacket {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_raw_fd(fd).expect("from_raw_fd failed")
}
}
#[derive(Debug)]
pub struct Datagram {
socket: Socket<Datagram>,
}
impl Datagram {
pub async fn bind(sa: SocketAddr) -> Result<Self> {
let socket = Socket::<Datagram>::new_datagram()?;
socket.bind(sa)?;
Ok(socket.into_datagram())
}
pub async fn connect(&self, sa: SocketAddr) -> Result<()> {
self.socket.connect_priv(sa).await
}
pub fn peer_addr(&self) -> Result<SocketAddr> {
self.socket.peer_addr_priv()
}
pub async fn send(&self, buf: &[u8]) -> Result<usize> {
self.socket.send_priv(buf).await
}
pub fn poll_send(&self, cx: &mut Context, buf: &[u8]) -> Poll<Result<usize>> {
self.socket.poll_send_priv(cx, buf)
}
pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> Result<usize> {
self.socket.send_to_priv(buf, target).await
}
pub fn poll_send_to(&self, cx: &mut Context, buf: &[u8], target: SocketAddr) -> Poll<Result<usize>> {
self.socket.poll_send_to_priv(cx, buf, target)
}
pub async fn recv(&self, buf: &mut [u8]) -> Result<usize> {
self.socket.recv_priv(buf).await
}
pub fn poll_recv(&self, cx: &mut Context, buf: &mut ReadBuf) -> Poll<Result<()>> {
self.socket.poll_recv_priv(cx, buf)
}
pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
self.socket.recv_from_priv(buf).await
}
pub fn poll_recv_from(&self, cx: &mut Context, buf: &mut ReadBuf) -> Poll<Result<SocketAddr>> {
self.socket.poll_recv_from_priv(cx, buf)
}
pub fn shutdown(&self, how: Shutdown) -> Result<()> {
self.socket.shutdown_priv(how)
}
pub fn send_mtu(&self) -> Result<usize> {
self.socket.send_mtu().map(|v| v.into())
}
pub fn recv_mtu(&self) -> Result<usize> {
self.socket.recv_mtu().map(|v| v.into())
}
pub unsafe fn from_raw_fd(fd: RawFd) -> Result<Self> {
Ok(Self { socket: Socket::from_raw_fd(fd)? })
}
}
impl AsRef<Socket<Datagram>> for Datagram {
fn as_ref(&self) -> &Socket<Datagram> {
&self.socket
}
}
impl AsRawFd for Datagram {
fn as_raw_fd(&self) -> RawFd {
self.socket.as_raw_fd()
}
}
impl FromRawFd for Datagram {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_raw_fd(fd).expect("from_raw_fd failed")
}
}