mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
59 lines
1.8 KiB
Rust
59 lines
1.8 KiB
Rust
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
use super::SyscallReturn;
|
|
use crate::{
|
|
fs::file_table::{FdFlags, FileDesc},
|
|
net::socket::unix::UnixStreamSocket,
|
|
prelude::*,
|
|
util::net::{CSocketAddrFamily, Protocol, SockFlags, SockType, SOCK_TYPE_MASK},
|
|
};
|
|
|
|
pub fn sys_socketpair(
|
|
domain: i32,
|
|
type_: i32,
|
|
protocol: i32,
|
|
sv: Vaddr,
|
|
ctx: &Context,
|
|
) -> Result<SyscallReturn> {
|
|
let domain = CSocketAddrFamily::try_from(domain)?;
|
|
let sock_type = SockType::try_from(type_ & SOCK_TYPE_MASK)?;
|
|
let sock_flags = SockFlags::from_bits_truncate(type_ & !SOCK_TYPE_MASK);
|
|
let protocol = Protocol::try_from(protocol)?;
|
|
|
|
debug!(
|
|
"domain = {:?}, sock_type = {:?}, sock_flags = {:?}, protocol = {:?}",
|
|
domain, sock_type, sock_flags, protocol
|
|
);
|
|
// TODO: deal with all sock_flags and protocol
|
|
let nonblocking = sock_flags.contains(SockFlags::SOCK_NONBLOCK);
|
|
let (socket_a, socket_b) = match (domain, sock_type) {
|
|
(CSocketAddrFamily::AF_UNIX, SockType::SOCK_STREAM) => {
|
|
UnixStreamSocket::new_pair(nonblocking)
|
|
}
|
|
_ => return_errno_with_message!(
|
|
Errno::EAFNOSUPPORT,
|
|
"cannot create socket pair for this family"
|
|
),
|
|
};
|
|
|
|
let socket_fds = {
|
|
let file_table = ctx.thread_local.file_table().borrow();
|
|
let mut file_table_locked = file_table.write();
|
|
let fd_flags = if sock_flags.contains(SockFlags::SOCK_CLOEXEC) {
|
|
FdFlags::CLOEXEC
|
|
} else {
|
|
FdFlags::empty()
|
|
};
|
|
let fd_a = file_table_locked.insert(socket_a, fd_flags);
|
|
let fd_b = file_table_locked.insert(socket_b, fd_flags);
|
|
SocketFds(fd_a, fd_b)
|
|
};
|
|
|
|
ctx.user_space().write_val(sv, &socket_fds)?;
|
|
Ok(SyscallReturn::Return(0))
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy, Pod)]
|
|
struct SocketFds(FileDesc, FileDesc);
|