use super::*;
use crate::{net::socket::SocketProperties, syscalls::*};
#[instrument(level = "trace", skip_all, fields(?af, ?ty, ?pt, sock = field::Empty), ret)]
pub fn sock_open<M: MemorySize>(
mut ctx: FunctionEnvMut<'_, WasiEnv>,
af: Addressfamily,
ty: Socktype,
pt: SockProto,
ro_sock: WasmPtr<WasiFd, M>,
) -> Result<Errno, WasiError> {
match pt {
SockProto::Tcp => {
if ty != Socktype::Stream {
return Ok(Errno::Notsup);
}
}
SockProto::Udp => {
if ty != Socktype::Dgram {
return Ok(Errno::Notsup);
}
}
_ => {}
}
let fd = wasi_try_ok!(sock_open_internal(&mut ctx, af, ty, pt, None)?);
#[cfg(feature = "journal")]
if ctx.data().enable_journal {
JournalEffector::save_sock_open(&mut ctx, af, ty, pt, fd).map_err(|err| {
tracing::error!("failed to save sock_open event - {}", err);
WasiError::Exit(ExitCode::from(Errno::Fault))
})?;
}
let env = ctx.data();
let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
wasi_try_mem_ok!(ro_sock.write(&memory, fd));
Ok(Errno::Success)
}
pub(crate) fn sock_open_internal(
ctx: &mut FunctionEnvMut<'_, WasiEnv>,
af: Addressfamily,
ty: Socktype,
pt: SockProto,
with_fd: Option<WasiFd>,
) -> Result<Result<WasiFd, Errno>, WasiError> {
let env = ctx.data();
let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
let kind = match ty {
Socktype::Stream | Socktype::Dgram => Kind::Socket {
socket: InodeSocket::new(InodeSocketKind::PreSocket {
props: SocketProperties {
family: af,
ty,
pt,
only_v6: false,
reuse_port: false,
reuse_addr: false,
no_delay: None,
keep_alive: None,
dont_route: None,
send_buf_size: None,
recv_buf_size: None,
write_timeout: None,
read_timeout: None,
accept_timeout: None,
connect_timeout: None,
handler: None,
},
addr: None,
}),
},
_ => return Ok(Err(Errno::Notsup)),
};
let inode =
state
.fs
.create_inode_with_default_stat(inodes, kind, false, "socket".to_string().into());
let rights = Rights::all_socket();
let fd = wasi_try_ok_ok!(if let Some(fd) = with_fd {
state
.fs
.with_fd(rights, rights, Fdflags::empty(), 0, inode, fd)
.map(|_| fd)
} else {
state
.fs
.create_fd(rights, rights, Fdflags::empty(), 0, inode)
});
Span::current().record("sock", fd);
Ok(Ok(fd))
}