Various unix socket fixes (+socketpair!)
This commit is contained in:
@@ -5,3 +5,12 @@ pub struct sockaddr_un {
|
||||
pub sun_family: sa_family_t,
|
||||
pub sun_path: [c_char; 108],
|
||||
}
|
||||
|
||||
impl sockaddr_un {
|
||||
pub fn path_len(&self) -> usize {
|
||||
let base = self as *const _ as usize;
|
||||
let path = &self.sun_path as *const _ as usize;
|
||||
trace!("base: {:#X}, path: {:#X}", base, path);
|
||||
path - base
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ impl PalEpoll for Sys {
|
||||
id: fd as usize,
|
||||
flags: syscall::EventFlags::from_bits(unsafe { (*event).events as usize })
|
||||
.expect("epoll: invalid bit pattern"),
|
||||
// NOTE: Danger when using non 64-bit systems. If this is
|
||||
// needed, use a box or something
|
||||
data: unsafe { mem::transmute((*event).data) },
|
||||
// NOTE: Danger when using something smaller than 64-bit
|
||||
// systems. If this is needed, use a box or something
|
||||
data: unsafe { (*event).data.u64 as usize },
|
||||
},
|
||||
) as c_int
|
||||
}
|
||||
@@ -102,7 +102,7 @@ impl PalEpoll for Sys {
|
||||
if bytes_read == -1 {
|
||||
return -1;
|
||||
}
|
||||
let read = bytes_read as usize / mem::size_of::<epoll_event>();
|
||||
let read = bytes_read as usize / mem::size_of::<syscall::Event>();
|
||||
|
||||
let mut count = 0;
|
||||
for i in 0..read {
|
||||
@@ -117,7 +117,7 @@ impl PalEpoll for Sys {
|
||||
}
|
||||
*event_ptr = epoll_event {
|
||||
events: event.flags.bits() as _,
|
||||
data: mem::transmute(event.data),
|
||||
data: epoll_data { u64: event.data as u64, },
|
||||
..Default::default()
|
||||
};
|
||||
count += 1;
|
||||
|
||||
@@ -32,13 +32,17 @@ macro_rules! bind_or_connect {
|
||||
0
|
||||
}};
|
||||
($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
|
||||
if ($address_len as usize) < mem::size_of::<sockaddr>() {
|
||||
if ($address_len as usize) < mem::size_of::<sa_family_t>() {
|
||||
errno = syscall::EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
let path = match (*$address).sa_family as c_int {
|
||||
AF_INET => {
|
||||
if ($address_len as usize) != mem::size_of::<sockaddr_in>() {
|
||||
errno = syscall::EINVAL;
|
||||
return -1;
|
||||
}
|
||||
let data = &*($address as *const sockaddr_in);
|
||||
let addr = slice::from_raw_parts(
|
||||
&data.sin_addr.s_addr as *const _ as *const u8,
|
||||
@@ -58,9 +62,10 @@ macro_rules! bind_or_connect {
|
||||
},
|
||||
AF_UNIX => {
|
||||
let data = &*($address as *const sockaddr_un);
|
||||
trace!("address: {:p}, data: {:p}, data2: {:#X}", $address, data, data as *const _ as usize);
|
||||
let addr = slice::from_raw_parts(
|
||||
&data.sun_path as *const _ as *const u8,
|
||||
mem::size_of_val(&data.sun_path),
|
||||
$address_len as usize - data.path_len(),
|
||||
);
|
||||
let path = format!(
|
||||
"{}",
|
||||
@@ -91,7 +96,7 @@ unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut so
|
||||
|
||||
let path = slice::from_raw_parts_mut(
|
||||
&mut data.sun_path as *mut _ as *mut u8,
|
||||
mem::size_of_val(&data.sun_path),
|
||||
data.path_len(),
|
||||
);
|
||||
|
||||
let len = cmp::min(path.len(), buf.len());
|
||||
@@ -165,6 +170,19 @@ unsafe fn inner_get_name(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn socket_kind(mut kind: c_int) -> (c_int, usize) {
|
||||
let mut flags = O_RDWR;
|
||||
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
|
||||
kind &= !SOCK_NONBLOCK;
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
|
||||
kind &= !SOCK_CLOEXEC;
|
||||
flags |= O_CLOEXEC;
|
||||
}
|
||||
(kind, flags)
|
||||
}
|
||||
|
||||
impl PalSocket for Sys {
|
||||
unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
|
||||
let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
|
||||
@@ -357,7 +375,7 @@ impl PalSocket for Sys {
|
||||
e(Err(syscall::Error::new(syscall::ENOSYS))) as c_int
|
||||
}
|
||||
|
||||
unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
|
||||
unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
|
||||
if domain != AF_INET && domain != AF_UNIX {
|
||||
errno = syscall::EAFNOSUPPORT;
|
||||
return -1;
|
||||
@@ -367,15 +385,7 @@ impl PalSocket for Sys {
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
let mut flags = O_RDWR;
|
||||
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
|
||||
kind &= !SOCK_NONBLOCK;
|
||||
flags |= O_NONBLOCK;
|
||||
}
|
||||
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
|
||||
kind &= !SOCK_CLOEXEC;
|
||||
flags |= O_CLOEXEC;
|
||||
}
|
||||
let (kind, flags) = socket_kind(kind);
|
||||
|
||||
// The tcp: and udp: schemes allow using no path,
|
||||
// and later specifying one using `dup`.
|
||||
@@ -386,19 +396,52 @@ impl PalSocket for Sys {
|
||||
_ => {
|
||||
errno = syscall::EPROTONOSUPPORT;
|
||||
-1
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn socketpair(domain: c_int, kind: c_int, protocol: c_int, sv: &mut [c_int; 2]) -> c_int {
|
||||
eprintln!(
|
||||
"socketpair({}, {}, {}, {:p})",
|
||||
domain,
|
||||
kind,
|
||||
protocol,
|
||||
sv.as_mut_ptr()
|
||||
);
|
||||
unsafe { errno = syscall::ENOSYS };
|
||||
return -1;
|
||||
let (kind, flags) = socket_kind(kind);
|
||||
|
||||
match (domain, kind) {
|
||||
(AF_UNIX, SOCK_STREAM) => {
|
||||
let listener = e(syscall::open("chan:", flags | O_CREAT));
|
||||
if listener == !0 {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// For now, chan: lets connects be instant, and instead blocks
|
||||
// on any I/O performed. So we don't need to mark this as
|
||||
// nonblocking.
|
||||
|
||||
let fd0 = e(syscall::dup(listener, b"connect"));
|
||||
if fd0 == !0 {
|
||||
let _ = syscall::close(listener);
|
||||
return -1;
|
||||
}
|
||||
|
||||
let fd1 = e(syscall::dup(listener, b"listen"));
|
||||
if fd1 == !0 {
|
||||
let _ = syscall::close(fd0);
|
||||
let _ = syscall::close(listener);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sv[0] = fd0 as c_int;
|
||||
sv[1] = fd1 as c_int;
|
||||
0
|
||||
},
|
||||
_ => unsafe {
|
||||
eprintln!(
|
||||
"socketpair({}, {}, {}, {:p})",
|
||||
domain,
|
||||
kind,
|
||||
protocol,
|
||||
sv.as_mut_ptr()
|
||||
);
|
||||
errno = syscall::EPROTONOSUPPORT;
|
||||
-1
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user