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
use super::{SocketAddr, ToSocketAddrs};
use crate::io;
use arceos_api::net::{self as api, AxUdpSocketHandle};
/// A UDP socket.
pub struct UdpSocket(AxUdpSocketHandle);
impl UdpSocket {
/// Creates a UDP socket from the given address.
///
/// The address type can be any implementor of [`ToSocketAddrs`] trait. See
/// its documentation for concrete examples.
///
/// If `addr` yields multiple addresses, `bind` will be attempted with
/// each of the addresses until one succeeds and returns the socket. If none
/// of the addresses succeed in creating a socket, the error returned from
/// the last attempt (the last address) is returned.
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
super::each_addr(addr, |addr: io::Result<&SocketAddr>| {
let addr = addr?;
let socket = api::ax_udp_socket();
api::ax_udp_bind(&socket, *addr)?;
Ok(UdpSocket(socket))
})
}
/// Returns the socket address that this socket was created from.
pub fn local_addr(&self) -> io::Result<SocketAddr> {
api::ax_udp_socket_addr(&self.0)
}
/// Returns the socket address of the remote peer this socket was connected to.
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
api::ax_udp_peer_addr(&self.0)
}
/// Receives a single datagram message on the socket. On success, returns
/// the number of bytes read and the origin.
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
api::ax_udp_recv_from(&self.0, buf)
}
/// Receives a single datagram message on the socket, without removing it from
/// the queue. On success, returns the number of bytes read and the origin.
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
api::ax_udp_peek_from(&self.0, buf)
}
/// Sends data on the socket to the given address. On success, returns the
/// number of bytes written.
///
/// Address type can be any implementor of [`ToSocketAddrs`] trait. See its
/// documentation for concrete examples.
///
/// It is possible for `addr` to yield multiple addresses, but `send_to`
/// will only send data to the first address yielded by `addr`.
pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
match addr.to_socket_addrs()?.next() {
Some(addr) => api::ax_udp_send_to(&self.0, buf, addr),
None => axerrno::ax_err!(InvalidInput, "no addresses to send data to"),
}
}
/// Connects this UDP socket to a remote address, allowing the `send` and
/// `recv` syscalls to be used to send data and also applies filters to only
/// receive data from the specified address.
///
/// If `addr` yields multiple addresses, `connect` will be attempted with
/// each of the addresses until the underlying OS function returns no
/// error. Note that usually, a successful `connect` call does not specify
/// that there is a remote server listening on the port, rather, such an
/// error would only be detected after the first send. If the OS returns an
/// error for each of the specified addresses, the error returned from the
/// last connection attempt (the last address) is returned.
pub fn connect(&self, addr: SocketAddr) -> io::Result<()> {
super::each_addr(addr, |addr: io::Result<&SocketAddr>| {
let addr = addr?;
api::ax_udp_connect(&self.0, *addr)
})
}
/// Sends data on the socket to the remote address to which it is connected.
///
/// [`UdpSocket::connect`] will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
api::ax_udp_send(&self.0, buf)
}
/// Receives a single datagram message on the socket from the remote address to
/// which it is connected. On success, returns the number of bytes read.
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
api::ax_udp_recv(&self.0, buf)
}
}