1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use std::io;
15 use std::os::fd::{AsRawFd, FromRawFd};
16 use std::os::unix::net;
17 use std::path::Path;
18
19 use libc::AF_UNIX;
20
21 use super::socket_addr::socket_addr_trans_un;
22 #[cfg(target_os = "macos")]
23 use crate::sys::socket::set_non_block;
24 use crate::sys::socket::socket_new;
25
bind(path: &Path) -> io::Result<net::UnixListener>26 pub(crate) fn bind(path: &Path) -> io::Result<net::UnixListener> {
27 let (socket_addr, addr_length) = socket_addr_trans_un(path)?;
28 let socket_addr = (&socket_addr as *const libc::sockaddr_un).cast::<libc::sockaddr>();
29
30 let socket = socket_new(AF_UNIX, libc::SOCK_STREAM)?;
31 let net = unsafe { net::UnixListener::from_raw_fd(socket) };
32
33 syscall!(bind(socket, socket_addr, addr_length))?;
34 // set backlog
35 syscall!(listen(socket, 1024))?;
36
37 Ok(net)
38 }
39
connect(path: &Path) -> io::Result<net::UnixStream>40 pub(crate) fn connect(path: &Path) -> io::Result<net::UnixStream> {
41 let (sockaddr, addr_length) = socket_addr_trans_un(path)?;
42 let sockaddr = (&sockaddr as *const libc::sockaddr_un).cast::<libc::sockaddr>();
43
44 let socket = socket_new(AF_UNIX, libc::SOCK_STREAM)?;
45 let net = unsafe { net::UnixStream::from_raw_fd(socket) };
46 match syscall!(connect(socket, sockaddr, addr_length)) {
47 Err(err) if err.raw_os_error() != Some(libc::EINPROGRESS) => Err(err),
48 _ => Ok(net),
49 }
50 }
51
unbound() -> io::Result<net::UnixDatagram>52 pub(crate) fn unbound() -> io::Result<net::UnixDatagram> {
53 let socket = socket_new(AF_UNIX, libc::SOCK_DGRAM)?;
54 let net = unsafe { net::UnixDatagram::from_raw_fd(socket) };
55 Ok(net)
56 }
57
data_gram_bind(path: &Path) -> io::Result<net::UnixDatagram>58 pub(crate) fn data_gram_bind(path: &Path) -> io::Result<net::UnixDatagram> {
59 let (socket_addr, addr_length) = socket_addr_trans_un(path)?;
60 let socket_addr = (&socket_addr as *const libc::sockaddr_un).cast::<libc::sockaddr>();
61
62 let socket = unbound()?;
63 match syscall!(bind(socket.as_raw_fd(), socket_addr, addr_length)) {
64 Err(err) => Err(err),
65 Ok(_) => Ok(socket),
66 }
67 }
68
stream_pair() -> io::Result<(net::UnixStream, net::UnixStream)>69 pub(crate) fn stream_pair() -> io::Result<(net::UnixStream, net::UnixStream)> {
70 pair(libc::SOCK_STREAM)
71 }
72
datagram_pair() -> io::Result<(net::UnixDatagram, net::UnixDatagram)>73 pub(crate) fn datagram_pair() -> io::Result<(net::UnixDatagram, net::UnixDatagram)> {
74 pair(libc::SOCK_DGRAM)
75 }
76
pair<T: FromRawFd>(socket_type: libc::c_int) -> io::Result<(T, T)>77 fn pair<T: FromRawFd>(socket_type: libc::c_int) -> io::Result<(T, T)> {
78 #[cfg(target_os = "linux")]
79 let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
80
81 // uninitialized fd
82 let mut fds = [-1; 2];
83 syscall!(socketpair(AF_UNIX, socket_type, 0, fds.as_mut_ptr()))?;
84
85 #[cfg(target_os = "macos")]
86 {
87 set_non_block(fds[0])?;
88 set_non_block(fds[1])?;
89 }
90
91 Ok(unsafe { (T::from_raw_fd(fds[0]), T::from_raw_fd(fds[1])) })
92 }
93