wasmer_wasix/syscalls/wasix/
sock_open.rs

1use super::*;
2use crate::{net::socket::SocketProperties, syscalls::*};
3
4/// ### `sock_open()`
5/// Create an endpoint for communication.
6///
7/// creates an endpoint for communication and returns a file descriptor
8/// tor that refers to that endpoint. The file descriptor returned by a successful
9/// call will be the lowest-numbered file descriptor not currently open
10/// for the process.
11///
12/// Note: This is similar to `socket` in POSIX using PF_INET
13///
14/// ## Parameters
15///
16/// * `af` - Address family
17/// * `socktype` - Socket type, either datagram or stream
18/// * `sock_proto` - Socket protocol
19///
20/// ## Return
21///
22/// The file descriptor of the socket that has been opened.
23#[instrument(level = "trace", skip_all, fields(?af, ?ty, ?pt, sock = field::Empty), ret)]
24pub fn sock_open<M: MemorySize>(
25    mut ctx: FunctionEnvMut<'_, WasiEnv>,
26    af: Addressfamily,
27    ty: Socktype,
28    pt: SockProto,
29    ro_sock: WasmPtr<WasiFd, M>,
30) -> Result<Errno, WasiError> {
31    WasiEnv::do_pending_operations(&mut ctx)?;
32
33    // only certain combinations are supported
34    match pt {
35        SockProto::Tcp => {
36            if ty != Socktype::Stream {
37                return Ok(Errno::Notsup);
38            }
39        }
40        SockProto::Udp => {
41            if ty != Socktype::Dgram {
42                return Ok(Errno::Notsup);
43            }
44        }
45        _ => {}
46    }
47
48    let fd = wasi_try_ok!(sock_open_internal(&mut ctx, af, ty, pt, None)?);
49
50    #[cfg(feature = "journal")]
51    if ctx.data().enable_journal {
52        JournalEffector::save_sock_open(&mut ctx, af, ty, pt, fd).map_err(|err| {
53            tracing::error!("failed to save sock_open event - {}", err);
54            WasiError::Exit(ExitCode::from(Errno::Fault))
55        })?;
56    }
57
58    let env = ctx.data();
59    let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
60    wasi_try_mem_ok!(ro_sock.write(&memory, fd));
61
62    Ok(Errno::Success)
63}
64
65pub(crate) fn sock_open_internal(
66    ctx: &mut FunctionEnvMut<'_, WasiEnv>,
67    af: Addressfamily,
68    ty: Socktype,
69    pt: SockProto,
70    with_fd: Option<WasiFd>,
71) -> Result<Result<WasiFd, Errno>, WasiError> {
72    let env = ctx.data();
73    let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
74
75    let kind = match ty {
76        Socktype::Stream | Socktype::Dgram => Kind::Socket {
77            socket: InodeSocket::new(InodeSocketKind::PreSocket {
78                props: SocketProperties {
79                    family: af,
80                    ty,
81                    pt,
82                    only_v6: false,
83                    reuse_port: false,
84                    reuse_addr: false,
85                    no_delay: None,
86                    keep_alive: None,
87                    dont_route: None,
88                    send_buf_size: None,
89                    recv_buf_size: None,
90                    write_timeout: None,
91                    read_timeout: None,
92                    accept_timeout: None,
93                    connect_timeout: None,
94                    handler: None,
95                },
96                addr: None,
97            }),
98        },
99        _ => return Ok(Err(Errno::Notsup)),
100    };
101
102    let inode =
103        state
104            .fs
105            .create_inode_with_default_stat(inodes, kind, false, "socket".to_string().into());
106    let rights = Rights::all_socket();
107    let fd = wasi_try_ok_ok!(if let Some(fd) = with_fd {
108        state
109            .fs
110            .with_fd(
111                rights,
112                rights,
113                Fdflags::empty(),
114                Fdflagsext::empty(),
115                0,
116                inode,
117                fd,
118            )
119            .map(|_| fd)
120    } else {
121        state.fs.create_fd(
122            rights,
123            rights,
124            Fdflags::empty(),
125            Fdflagsext::empty(),
126            0,
127            inode,
128        )
129    });
130    Span::current().record("sock", fd);
131
132    Ok(Ok(fd))
133}