1use core::net::SocketAddr;
2
3use alloc::sync::Arc;
4use axerrno::{LinuxError, LinuxResult};
5use axio::PollState;
6use axnet::{TcpSocket, UdpSocket};
7use axsync::Mutex;
8use linux_raw_sys::general::S_IFSOCK;
9
10use super::{FileLike, Kstat};
11
12pub enum Socket {
13 Udp(Mutex<UdpSocket>),
14 Tcp(Mutex<TcpSocket>),
15}
16
17macro_rules! impl_socket {
18 ($pub:vis fn $name:ident(&self $(,$arg:ident: $arg_ty:ty)*) -> $ret:ty) => {
19 $pub fn $name(&self, $($arg: $arg_ty),*) -> $ret {
20 match self {
21 Socket::Udp(udpsocket) => Ok(udpsocket.lock().$name($($arg),*)?),
22 Socket::Tcp(tcpsocket) => Ok(tcpsocket.lock().$name($($arg),*)?),
23 }
24 }
25 };
26}
27
28impl Socket {
29 pub fn recv(&self, buf: &mut [u8]) -> LinuxResult<usize> {
30 match self {
31 Socket::Udp(udpsocket) => Ok(udpsocket.lock().recv_from(buf).map(|e| e.0)?),
32 Socket::Tcp(tcpsocket) => Ok(tcpsocket.lock().recv(buf)?),
33 }
34 }
35
36 pub fn sendto(&self, buf: &[u8], addr: SocketAddr) -> LinuxResult<usize> {
37 match self {
38 Socket::Udp(udpsocket) => Ok(udpsocket.lock().send_to(buf, addr)?),
40 Socket::Tcp(_) => Err(LinuxError::EISCONN),
41 }
42 }
43
44 pub fn recvfrom(&self, buf: &mut [u8]) -> LinuxResult<(usize, Option<SocketAddr>)> {
45 match self {
46 Socket::Udp(udpsocket) => Ok(udpsocket
48 .lock()
49 .recv_from(buf)
50 .map(|res| (res.0, Some(res.1)))?),
51 Socket::Tcp(tcpsocket) => Ok(tcpsocket.lock().recv(buf).map(|res| (res, None))?),
52 }
53 }
54
55 pub fn listen(&self) -> LinuxResult {
56 match self {
57 Socket::Udp(_) => Err(LinuxError::EOPNOTSUPP),
58 Socket::Tcp(tcpsocket) => Ok(tcpsocket.lock().listen()?),
59 }
60 }
61
62 pub fn accept(&self) -> LinuxResult<TcpSocket> {
63 match self {
64 Socket::Udp(_) => Err(LinuxError::EOPNOTSUPP),
65 Socket::Tcp(tcpsocket) => Ok(tcpsocket.lock().accept()?),
66 }
67 }
68
69 impl_socket!(pub fn send(&self, buf: &[u8]) -> LinuxResult<usize>);
70 impl_socket!(pub fn poll(&self) -> LinuxResult<PollState>);
71 impl_socket!(pub fn local_addr(&self) -> LinuxResult<SocketAddr>);
72 impl_socket!(pub fn peer_addr(&self) -> LinuxResult<SocketAddr>);
73 impl_socket!(pub fn bind(&self, addr: SocketAddr) -> LinuxResult);
74 impl_socket!(pub fn connect(&self, addr: SocketAddr) -> LinuxResult);
75 impl_socket!(pub fn shutdown(&self) -> LinuxResult);
76}
77
78impl FileLike for Socket {
79 fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> {
80 self.recv(buf)
81 }
82
83 fn write(&self, buf: &[u8]) -> LinuxResult<usize> {
84 self.send(buf)
85 }
86
87 fn stat(&self) -> LinuxResult<Kstat> {
88 Ok(Kstat {
90 mode: S_IFSOCK | 0o777u32, blksize: 4096,
92 ..Default::default()
93 })
94 }
95
96 fn into_any(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
97 self
98 }
99
100 fn poll(&self) -> LinuxResult<PollState> {
101 self.poll()
102 }
103
104 fn set_nonblocking(&self, nonblock: bool) -> LinuxResult {
105 match self {
106 Socket::Udp(udpsocket) => udpsocket.lock().set_nonblocking(nonblock),
107 Socket::Tcp(tcpsocket) => tcpsocket.lock().set_nonblocking(nonblock),
108 }
109 Ok(())
110 }
111}