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
use super::{SocketAddr, ToSocketAddrs};
use crate::io::{self, prelude::*};
use arceos_api::net::{self as api, AxTcpSocketHandle};
/// A TCP stream between a local and a remote socket.
pub struct TcpStream(AxTcpSocketHandle);
/// A TCP socket server, listening for connections.
pub struct TcpListener(AxTcpSocketHandle);
impl TcpStream {
/// Opens a TCP connection to a remote host.
///
/// `addr` is an address of the remote host. Anything which implements
/// [`ToSocketAddrs`] trait can be supplied for the address; see this trait
/// documentation for concrete examples.
///
/// If `addr` yields multiple addresses, `connect` will be attempted with
/// each of the addresses until a connection is successful. If none of
/// the addresses result in a successful connection, the error returned from
/// the last connection attempt (the last address) is returned.
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
super::each_addr(addr, |addr: io::Result<&SocketAddr>| {
let addr = addr?;
let socket = api::ax_tcp_socket();
api::ax_tcp_connect(&socket, *addr)?;
Ok(TcpStream(socket))
})
}
/// Returns the socket address of the local half of this TCP connection.
pub fn local_addr(&self) -> io::Result<SocketAddr> {
api::ax_tcp_socket_addr(&self.0)
}
/// Returns the socket address of the remote peer of this TCP connection.
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
api::ax_tcp_peer_addr(&self.0)
}
/// Shuts down the connection.
pub fn shutdown(&self) -> io::Result<()> {
api::ax_tcp_shutdown(&self.0)
}
}
impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
api::ax_tcp_recv(&self.0, buf)
}
}
impl Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
api::ax_tcp_send(&self.0, buf)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl TcpListener {
/// Creates a new `TcpListener` which will be bound to the specified
/// address.
///
/// The returned listener is ready for accepting connections.
///
/// Binding with a port number of 0 will request that the OS assigns a port
/// to this listener. The port allocated can be queried via the
/// [`TcpListener::local_addr`] method.
///
/// 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 listener. If
/// none of the addresses succeed in creating a listener, the error returned
/// from the last attempt (the last address) is returned.
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
super::each_addr(addr, |addr: io::Result<&SocketAddr>| {
let addr = addr?;
let backlog = 128;
let socket = api::ax_tcp_socket();
api::ax_tcp_bind(&socket, *addr)?;
api::ax_tcp_listen(&socket, backlog)?;
Ok(TcpListener(socket))
})
}
/// Returns the local socket address of this listener.
pub fn local_addr(&self) -> io::Result<SocketAddr> {
api::ax_tcp_socket_addr(&self.0)
}
/// Accept a new incoming connection from this listener.
///
/// This function will block the calling thread until a new TCP connection
/// is established. When established, the corresponding [`TcpStream`] and the
/// remote peer's address will be returned.
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
api::ax_tcp_accept(&self.0).map(|(a, b)| (TcpStream(a), b))
}
}