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 arceos_api::net::{self as api, AxUdpSocketHandle};
use super::{SocketAddr, ToSocketAddrs};
use crate::io;
/// 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)
}
}