mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 21:51:32 +00:00
improve networking in emscripten
This commit is contained in:
@ -135,7 +135,8 @@ pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
|
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
|
||||||
trace!("emscripten::_pthread_create");
|
trace!("emscripten::_pthread_create");
|
||||||
0
|
// 11 seems to mean "no"
|
||||||
|
11
|
||||||
}
|
}
|
||||||
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
|
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||||
trace!("emscripten::_pthread_detach");
|
trace!("emscripten::_pthread_detach");
|
||||||
|
6
lib/emscripten/src/env/unix/mod.rs
vendored
6
lib/emscripten/src/env/unix/mod.rs
vendored
@ -220,10 +220,10 @@ pub fn _getaddrinfo(
|
|||||||
.deref(memory)
|
.deref(memory)
|
||||||
.map(|m| m as *const Cell<c_char> as *const c_char))
|
.map(|m| m as *const Cell<c_char> as *const c_char))
|
||||||
.unwrap_or(std::ptr::null()),
|
.unwrap_or(std::ptr::null()),
|
||||||
(service_str_ptr
|
service_str_ptr
|
||||||
.deref(memory)
|
.deref(memory)
|
||||||
.map(|m| m as *const Cell<c_char> as *const c_char))
|
.map(|m| m as *const Cell<c_char> as *const c_char)
|
||||||
.unwrap_or(std::ptr::null()),
|
.unwrap_or(std::ptr::null()),
|
||||||
hints
|
hints
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|h| h as *const addrinfo)
|
.map(|h| h as *const addrinfo)
|
||||||
|
@ -21,9 +21,9 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u
|
|||||||
|
|
||||||
/// emscripten: _emscripten_get_heap_size
|
/// emscripten: _emscripten_get_heap_size
|
||||||
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
|
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
|
||||||
debug!("emscripten::_emscripten_get_heap_size");
|
trace!("emscripten::_emscripten_get_heap_size");
|
||||||
let result = ctx.memory(0).size().bytes().0 as u32;
|
let result = ctx.memory(0).size().bytes().0 as u32;
|
||||||
debug!("=> {}", result);
|
trace!("=> {}", result);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -279,28 +279,38 @@ pub fn ___syscall75(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|||||||
// readlink
|
// readlink
|
||||||
pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
|
||||||
debug!("emscripten::___syscall85 (readlink)");
|
debug!("emscripten::___syscall85 (readlink)");
|
||||||
let _path = varargs.get_str(ctx);
|
let pathname_addr = varargs.get_str(ctx);
|
||||||
let buf = varargs.get_str(ctx);
|
let buf = varargs.get_str(ctx);
|
||||||
// let buf_addr: i32 = varargs.get(ctx);
|
// let buf_addr: i32 = varargs.get(ctx);
|
||||||
let buf_size: i32 = varargs.get(ctx);
|
let buf_size: i32 = varargs.get(ctx);
|
||||||
let fd = 3;
|
let real_path_owned = get_cstr_path(ctx, pathname_addr);
|
||||||
let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 };
|
let real_path = if let Some(ref rp) = real_path_owned {
|
||||||
|
rp.as_c_str().as_ptr()
|
||||||
|
} else {
|
||||||
|
pathname_addr
|
||||||
|
};
|
||||||
|
// let fd = 3;
|
||||||
|
// let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 };
|
||||||
|
// debug!(
|
||||||
|
// "=> buf: {}, buf_size: {}, return: {} ",
|
||||||
|
// unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
|
||||||
|
// buf_size,
|
||||||
|
// ret
|
||||||
|
// );
|
||||||
|
let ret = unsafe { libc::readlink(real_path, buf as _, buf_size as _) as i32 };
|
||||||
|
if ret == -1 {
|
||||||
|
debug!("readlink failed");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
debug!(
|
debug!(
|
||||||
"=> buf: {}, buf_size: {}, return: {} ",
|
"=> path: {}, buf: {}, buf_size: {}, return: {} ",
|
||||||
|
unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() },
|
||||||
unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
|
unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
|
||||||
|
// std::ffi::CStr::from_ptr(buf).to_str().unwrap(),
|
||||||
|
// buf,
|
||||||
buf_size,
|
buf_size,
|
||||||
ret
|
ret
|
||||||
);
|
);
|
||||||
// let ret = unsafe {
|
|
||||||
// readlink(path, buf as _, buf_size as _) as i32
|
|
||||||
// };
|
|
||||||
// debug!("=> path: {}, buf: {}, buf_size: {}, return: {} ",
|
|
||||||
// unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() },
|
|
||||||
// unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
|
|
||||||
// // std::ffi::CStr::from_ptr(buf).to_str().unwrap(),
|
|
||||||
// // buf,
|
|
||||||
// buf_size,
|
|
||||||
// ret);
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,11 +541,6 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ___syscall168(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
|
||||||
debug!("emscripten::___syscall168 - stub");
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ___syscall191(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
pub fn ___syscall191(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
let _resource: i32 = varargs.get(ctx);
|
let _resource: i32 = varargs.get(ctx);
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -72,14 +72,14 @@ use libc::{
|
|||||||
F_GETFD,
|
F_GETFD,
|
||||||
F_SETFD,
|
F_SETFD,
|
||||||
SOL_SOCKET,
|
SOL_SOCKET,
|
||||||
SO_REUSEADDR,
|
|
||||||
TIOCGWINSZ,
|
TIOCGWINSZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx};
|
||||||
|
|
||||||
|
use crate::env::EmSockAddr;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
@ -101,9 +101,9 @@ use libc::{fallocate, fdatasync, ftruncate64, lstat, madvise, wait4};
|
|||||||
// Another conditional constant for name resolution: Macos et iOS use
|
// Another conditional constant for name resolution: Macos et iOS use
|
||||||
// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
|
// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
|
||||||
// Other platforms do otherwise.
|
// Other platforms do otherwise.
|
||||||
#[cfg(target_os = "darwin")]
|
#[cfg(target_os = "macos")]
|
||||||
use libc::SO_NOSIGPIPE;
|
use libc::SO_NOSIGPIPE;
|
||||||
#[cfg(not(target_os = "darwin"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
const SO_NOSIGPIPE: c_int = 0;
|
const SO_NOSIGPIPE: c_int = 0;
|
||||||
|
|
||||||
/// open
|
/// open
|
||||||
@ -444,6 +444,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
let call: u32 = varargs.get(ctx);
|
let call: u32 = varargs.get(ctx);
|
||||||
let mut socket_varargs: VarArgs = varargs.get(ctx);
|
let mut socket_varargs: VarArgs = varargs.get(ctx);
|
||||||
|
|
||||||
|
// migrating to EmSockAddr, port being separate here is nice, should update that too
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct GuestSockaddrIn {
|
pub struct GuestSockaddrIn {
|
||||||
pub sin_family: sa_family_t, // u16
|
pub sin_family: sa_family_t, // u16
|
||||||
@ -458,13 +459,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
pub s_addr: in_addr_t, // u32
|
pub s_addr: in_addr_t, // u32
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug!("GuestSockaddrIn = {}", size_of::<GuestSockaddrIn>());
|
|
||||||
|
|
||||||
pub struct LinuxSockAddr {
|
|
||||||
pub sa_family: u16,
|
|
||||||
pub sa_data: [c_char; 14],
|
|
||||||
}
|
|
||||||
|
|
||||||
match call {
|
match call {
|
||||||
1 => {
|
1 => {
|
||||||
debug!("socket: socket");
|
debug!("socket: socket");
|
||||||
@ -487,6 +481,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
unimplemented!("non blocking sockets");
|
unimplemented!("non blocking sockets");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// why is this here?
|
||||||
type T = u32;
|
type T = u32;
|
||||||
let payload = 1 as *const T as _;
|
let payload = 1 as *const T as _;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -500,7 +495,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}",
|
"=> domain: {}, type: {}, protocol: {} = fd: {}",
|
||||||
domain, ty, protocol, fd
|
domain, ty, protocol, fd
|
||||||
);
|
);
|
||||||
fd as _
|
fd as _
|
||||||
@ -555,47 +550,75 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
5 => {
|
5 => {
|
||||||
debug!("socket: accept");
|
debug!("socket: accept");
|
||||||
// accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
|
// accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
|
||||||
let socket = socket_varargs.get(ctx);
|
let socket: i32 = socket_varargs.get(ctx);
|
||||||
let address_addr: u32 = socket_varargs.get(ctx);
|
let address: WasmPtr<EmSockAddr> = socket_varargs.get(ctx);
|
||||||
let address_len: u32 = socket_varargs.get(ctx);
|
let address_len: WasmPtr<u32> = socket_varargs.get(ctx);
|
||||||
let address = emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut sockaddr;
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"=> socket: {}, address: {:?}, address_len: {}",
|
"=> socket: {}, address: {:?}, address_len: {}",
|
||||||
socket, address, address_len
|
socket,
|
||||||
|
address.deref(ctx.memory(0)).unwrap().get(),
|
||||||
|
address_len.deref(ctx.memory(0)).unwrap().get()
|
||||||
);
|
);
|
||||||
let address_len_addr =
|
let address_len_addr =
|
||||||
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
|
unsafe { address_len.deref_mut(ctx.memory(0)).unwrap().get_mut() };
|
||||||
// let mut address_len_addr: socklen_t = 0;
|
// let mut address_len_addr: socklen_t = 0;
|
||||||
|
|
||||||
let fd = unsafe { accept(socket, address, address_len_addr) };
|
let (fd, host_address) = unsafe {
|
||||||
|
let mut host_address: sockaddr = std::mem::uninitialized();
|
||||||
|
let fd = accept(socket, &mut host_address, address_len_addr);
|
||||||
|
|
||||||
unsafe {
|
(fd, host_address)
|
||||||
let address_linux =
|
|
||||||
emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr;
|
|
||||||
(*address_linux).sa_family = (*address).sa_family as u16;
|
|
||||||
(*address_linux).sa_data = (*address).sa_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let address_addr = unsafe { address.deref_mut(ctx.memory(0)).unwrap().get_mut() };
|
||||||
|
|
||||||
|
address_addr.sa_family = host_address.sa_family as _;
|
||||||
|
address_addr.sa_data = host_address.sa_data.clone();
|
||||||
|
|
||||||
|
// why is this here?
|
||||||
// set_cloexec
|
// set_cloexec
|
||||||
unsafe {
|
unsafe {
|
||||||
ioctl(fd, FIOCLEX);
|
ioctl(fd, FIOCLEX);
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("fd: {}", fd);
|
debug!(
|
||||||
|
"address: {:?}, len: {}, result fd = {}",
|
||||||
|
address_addr, address_len_addr, fd
|
||||||
|
);
|
||||||
|
|
||||||
fd as _
|
fd as _
|
||||||
}
|
}
|
||||||
6 => {
|
6 => {
|
||||||
debug!("socket: getsockname");
|
debug!("socket: getsockname");
|
||||||
// getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
|
// getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
|
||||||
let socket = socket_varargs.get(ctx);
|
let socket: i32 = socket_varargs.get(ctx);
|
||||||
let address: u32 = socket_varargs.get(ctx);
|
let address: WasmPtr<EmSockAddr> = socket_varargs.get(ctx);
|
||||||
let address_len: u32 = socket_varargs.get(ctx);
|
let address_len: WasmPtr<u32> = socket_varargs.get(ctx);
|
||||||
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
|
|
||||||
let address_len_addr =
|
let address_len_addr =
|
||||||
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
|
unsafe { address_len.deref_mut(ctx.memory(0)).unwrap().get_mut() };
|
||||||
unsafe { getsockname(socket, address, address_len_addr) }
|
|
||||||
|
let (ret, sock_addr_host) = unsafe {
|
||||||
|
// read host data into new var
|
||||||
|
let mut address: sockaddr = std::mem::uninitialized();
|
||||||
|
let ret = getsockname(
|
||||||
|
socket,
|
||||||
|
&mut address as *mut sockaddr,
|
||||||
|
address_len_addr as *mut u32,
|
||||||
|
);
|
||||||
|
(ret, address)
|
||||||
|
};
|
||||||
|
// translate from host data into emscripten data
|
||||||
|
let mut address_mut = unsafe { address.deref_mut(ctx.memory(0)).unwrap().get_mut() };
|
||||||
|
address_mut.sa_family = sock_addr_host.sa_family as _;
|
||||||
|
address_mut.sa_data = sock_addr_host.sa_data.clone();
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"=> socket: {}, address, {:?}, address_len: {}, result = {}",
|
||||||
|
socket, address_mut, address_len_addr, ret
|
||||||
|
);
|
||||||
|
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
7 => {
|
7 => {
|
||||||
debug!("socket: getpeername");
|
debug!("socket: getpeername");
|
||||||
@ -647,25 +670,23 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
}
|
}
|
||||||
14 => {
|
14 => {
|
||||||
debug!("socket: setsockopt");
|
debug!("socket: setsockopt");
|
||||||
// NOTE: Emscripten seems to be passing the wrong values to this syscall
|
// OSX and BSD have completely different values, be very careful here
|
||||||
// level: Em passes 1 as SOL_SOCKET; SOL_SOCKET is 0xffff in BSD
|
|
||||||
// name: Em passes SO_ACCEPTCONN, but Nginx complains about REUSEADDR
|
|
||||||
// https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156
|
// https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156
|
||||||
// setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int
|
// setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int
|
||||||
|
|
||||||
let socket = socket_varargs.get(ctx);
|
let socket = socket_varargs.get(ctx);
|
||||||
let level: i32 = socket_varargs.get(ctx);
|
let level: i32 = socket_varargs.get(ctx);
|
||||||
// SOL_SOCKET = 0xffff (BSD, OSX)
|
|
||||||
let level = if level == 1 { SOL_SOCKET } else { level };
|
let level = if level == 1 { SOL_SOCKET } else { level };
|
||||||
let name: i32 = socket_varargs.get(ctx);
|
let untranslated_name: i32 = socket_varargs.get(ctx);
|
||||||
// SO_REUSEADDR = 0x4 (BSD, OSX)
|
|
||||||
let name = if name == 2 { SO_REUSEADDR } else { name };
|
|
||||||
let value: u32 = socket_varargs.get(ctx);
|
let value: u32 = socket_varargs.get(ctx);
|
||||||
let option_len = socket_varargs.get(ctx);
|
let option_len: u32 = socket_varargs.get(ctx);
|
||||||
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; // Endian problem
|
let value_addr =
|
||||||
|
emscripten_memory_pointer!(ctx.memory(0), value) as *const libc::c_void;
|
||||||
|
let name: i32 = translate_socket_name_flag(untranslated_name);
|
||||||
|
|
||||||
let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
|
let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
|
||||||
|
|
||||||
debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
|
debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, untranslated_name, value_addr, option_len, ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
15 => {
|
15 => {
|
||||||
@ -673,7 +694,9 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
// getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int
|
// getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int
|
||||||
let socket = socket_varargs.get(ctx);
|
let socket = socket_varargs.get(ctx);
|
||||||
let level: i32 = socket_varargs.get(ctx);
|
let level: i32 = socket_varargs.get(ctx);
|
||||||
let name: i32 = socket_varargs.get(ctx);
|
let level = if level == 1 { SOL_SOCKET } else { level };
|
||||||
|
let untranslated_name: i32 = socket_varargs.get(ctx);
|
||||||
|
let name: i32 = translate_socket_name_flag(untranslated_name);
|
||||||
let value: u32 = socket_varargs.get(ctx);
|
let value: u32 = socket_varargs.get(ctx);
|
||||||
let option_len: u32 = socket_varargs.get(ctx);
|
let option_len: u32 = socket_varargs.get(ctx);
|
||||||
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _;
|
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _;
|
||||||
@ -706,6 +729,60 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// OSX and BSD have completely different values, we must translate from emscripten's Linuxy
|
||||||
|
/// value into one that we can pass to native syscalls
|
||||||
|
fn translate_socket_name_flag(name: i32) -> i32 {
|
||||||
|
match name {
|
||||||
|
2 => libc::SO_REUSEADDR,
|
||||||
|
3 => libc::SO_TYPE,
|
||||||
|
4 => libc::SO_ERROR,
|
||||||
|
5 => libc::SO_DONTROUTE,
|
||||||
|
6 => libc::SO_BROADCAST,
|
||||||
|
7 => libc::SO_SNDBUF,
|
||||||
|
8 => libc::SO_RCVBUF,
|
||||||
|
9 => libc::SO_KEEPALIVE,
|
||||||
|
10 => libc::SO_OOBINLINE,
|
||||||
|
13 => libc::SO_LINGER,
|
||||||
|
18 => libc::SO_RCVLOWAT,
|
||||||
|
19 => libc::SO_SNDLOWAT,
|
||||||
|
20 => libc::SO_RCVTIMEO,
|
||||||
|
21 => libc::SO_SNDTIMEO,
|
||||||
|
// SO_DEBUG missing
|
||||||
|
30 => libc::SO_ACCEPTCONN,
|
||||||
|
otherwise => otherwise,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct EmPollFd {
|
||||||
|
pub fd: i32,
|
||||||
|
pub events: i16,
|
||||||
|
pub revents: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl wasmer_runtime_core::types::ValueType for EmPollFd {}
|
||||||
|
|
||||||
|
/// poll
|
||||||
|
pub fn ___syscall168(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||||
|
debug!("emscripten::___syscall168(poll)");
|
||||||
|
let fds: WasmPtr<EmPollFd> = varargs.get(ctx);
|
||||||
|
let nfds: u32 = varargs.get(ctx);
|
||||||
|
let timeout: i32 = varargs.get(ctx);
|
||||||
|
|
||||||
|
let fds_mut = unsafe { fds.deref_mut(ctx.memory(0)).unwrap().get_mut() };
|
||||||
|
|
||||||
|
let ret = unsafe {
|
||||||
|
libc::poll(
|
||||||
|
fds_mut as *mut EmPollFd as *mut libc::pollfd,
|
||||||
|
nfds as _,
|
||||||
|
timeout,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
// pread
|
// pread
|
||||||
pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||||
debug!("emscripten::___syscall180 (pread) {}", _which);
|
debug!("emscripten::___syscall180 (pread) {}", _which);
|
||||||
@ -885,11 +962,11 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
|||||||
|
|
||||||
let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8;
|
let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8;
|
||||||
|
|
||||||
let mut opened_dirs = &mut get_emscripten_data(ctx).opened_dirs;
|
let opened_dirs = &mut get_emscripten_data(ctx).opened_dirs;
|
||||||
|
|
||||||
// need to persist stream across calls?
|
// need to persist stream across calls?
|
||||||
// let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
|
// let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
|
||||||
let mut dir = &*opened_dirs
|
let dir = &*opened_dirs
|
||||||
.entry(fd)
|
.entry(fd)
|
||||||
.or_insert_with(|| unsafe { Box::new(libc::fdopendir(fd)) });
|
.or_insert_with(|| unsafe { Box::new(libc::fdopendir(fd)) });
|
||||||
|
|
||||||
|
@ -255,6 +255,12 @@ pub fn ___syscall122(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_i
|
|||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// poll
|
||||||
|
pub fn ___syscall168(_ctx: &mut Ctx, _which: i32, _varargs: VarArgs) -> i32 {
|
||||||
|
debug!("emscripten::___syscall168(poll) - stub");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
/// lstat64
|
/// lstat64
|
||||||
pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
|
||||||
debug!("emscripten::___syscall196 (lstat64) - stub");
|
debug!("emscripten::___syscall196 (lstat64) - stub");
|
||||||
|
@ -46,7 +46,9 @@ fn align_pointer(ptr: usize, align: usize) -> usize {
|
|||||||
impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
|
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
|
||||||
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
if self.offset == 0
|
||||||
|
|| (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -60,7 +62,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell<T>> {
|
pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell<T>> {
|
||||||
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
|
if self.offset == 0
|
||||||
|
|| (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let cell_ptr = align_pointer(
|
let cell_ptr = align_pointer(
|
||||||
@ -79,7 +83,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
||||||
let slice_full_len = index as usize + length as usize;
|
let slice_full_len = index as usize + length as usize;
|
||||||
|
|
||||||
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
|
if self.offset == 0
|
||||||
|
|| (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +112,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
|||||||
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
|
||||||
let slice_full_len = index as usize + length as usize;
|
let slice_full_len = index as usize + length as usize;
|
||||||
|
|
||||||
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
|
if self.offset == 0
|
||||||
|
|| (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user