use arceos_api::net::{self as api, AxTcpSocketHandle};
use super::{SocketAddr, ToSocketAddrs};
use crate::io::{self, prelude::*};
pub struct TcpStream(AxTcpSocketHandle);
pub struct TcpListener(AxTcpSocketHandle);
impl TcpStream {
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))
})
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
api::ax_tcp_socket_addr(&self.0)
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
api::ax_tcp_peer_addr(&self.0)
}
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 {
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))
})
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
api::ax_tcp_socket_addr(&self.0)
}
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
api::ax_tcp_accept(&self.0).map(|(a, b)| (TcpStream(a), b))
}
}