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 if ty != Socktype::Stream => {
36            return Ok(Errno::Notsup);
37        }
38        SockProto::Udp if ty != Socktype::Dgram => {
39            return Ok(Errno::Notsup);
40        }
41        _ => {}
42    }
43
44    let fd = wasi_try_ok!(sock_open_internal(&mut ctx, af, ty, pt, None)?);
45
46    #[cfg(feature = "journal")]
47    if ctx.data().enable_journal {
48        JournalEffector::save_sock_open(&mut ctx, af, ty, pt, fd).map_err(|err| {
49            tracing::error!("failed to save sock_open event - {}", err);
50            WasiError::Exit(ExitCode::from(Errno::Fault))
51        })?;
52    }
53
54    let env = ctx.data();
55    let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
56    wasi_try_mem_ok!(ro_sock.write(&memory, fd));
57
58    Ok(Errno::Success)
59}
60
61pub(crate) fn sock_open_internal(
62    ctx: &mut FunctionEnvMut<'_, WasiEnv>,
63    af: Addressfamily,
64    ty: Socktype,
65    pt: SockProto,
66    with_fd: Option<WasiFd>,
67) -> Result<Result<WasiFd, Errno>, WasiError> {
68    let env = ctx.data();
69    let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
70
71    let kind = match ty {
72        Socktype::Stream | Socktype::Dgram => Kind::Socket {
73            socket: InodeSocket::new(InodeSocketKind::PreSocket {
74                props: SocketProperties {
75                    family: af,
76                    ty,
77                    pt,
78                    only_v6: false,
79                    reuse_port: false,
80                    reuse_addr: false,
81                    no_delay: None,
82                    keep_alive: None,
83                    dont_route: None,
84                    send_buf_size: None,
85                    recv_buf_size: None,
86                    write_timeout: None,
87                    read_timeout: None,
88                    accept_timeout: None,
89                    connect_timeout: None,
90                    handler: None,
91                },
92                addr: None,
93            }),
94        },
95        _ => return Ok(Err(Errno::Notsup)),
96    };
97
98    let inode =
99        state
100            .fs
101            .create_inode_with_default_stat(inodes, kind, false, "socket".to_string().into());
102    let rights = Rights::all_socket();
103    let fd = wasi_try_ok_ok!(if let Some(fd) = with_fd {
104        state
105            .fs
106            .with_fd(
107                rights,
108                rights,
109                Fdflags::empty(),
110                Fdflagsext::empty(),
111                0,
112                inode,
113                fd,
114            )
115            .map(|_| fd)
116    } else {
117        state.fs.create_fd(
118            rights,
119            rights,
120            Fdflags::empty(),
121            Fdflagsext::empty(),
122            0,
123            inode,
124        )
125    });
126    Span::current().record("sock", fd);
127
128    Ok(Ok(fd))
129}