mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-18 03:11:21 +00:00
Merge #514
514: improve emscripten sockets and networking r=MarkMcCaskey a=MarkMcCaskey Co-authored-by: Mark McCaskey <mark@wasmer.io>
This commit is contained in:
@ -15,12 +15,12 @@ pub fn exit_with_live_runtime(_ctx: &mut Ctx) {
|
||||
}
|
||||
|
||||
pub fn setTempRet0(ctx: &mut Ctx, val: i32) {
|
||||
debug!("emscripten::setTempRet0: {}", val);
|
||||
trace!("emscripten::setTempRet0: {}", val);
|
||||
get_emscripten_data(ctx).temp_ret_0 = val;
|
||||
}
|
||||
|
||||
pub fn getTempRet0(ctx: &mut Ctx) -> i32 {
|
||||
debug!("emscripten::getTempRet0");
|
||||
trace!("emscripten::getTempRet0");
|
||||
get_emscripten_data(ctx).temp_ret_0
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_attr_destroy");
|
||||
trace!("emscripten::_pthread_attr_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_getstack(
|
||||
@ -88,136 +88,136 @@ pub fn _pthread_attr_getstack(
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_attr_init({})", _a);
|
||||
trace!("emscripten::_pthread_attr_init({})", _a);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_attr_setstacksize(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_attr_setstacksize");
|
||||
trace!("emscripten::_pthread_attr_setstacksize");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cleanup_pop(_ctx: &mut Ctx, _a: i32) -> () {
|
||||
debug!("emscripten::_pthread_cleanup_pop");
|
||||
trace!("emscripten::_pthread_cleanup_pop");
|
||||
}
|
||||
pub fn _pthread_cleanup_push(_ctx: &mut Ctx, _a: i32, _b: i32) -> () {
|
||||
debug!("emscripten::_pthread_cleanup_push");
|
||||
trace!("emscripten::_pthread_cleanup_push");
|
||||
}
|
||||
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_destroy");
|
||||
trace!("emscripten::_pthread_cond_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_init");
|
||||
trace!("emscripten::_pthread_cond_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_signal");
|
||||
trace!("emscripten::_pthread_cond_signal");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_timedwait(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_timedwait");
|
||||
trace!("emscripten::_pthread_cond_timedwait");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_cond_wait");
|
||||
trace!("emscripten::_pthread_cond_wait");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_condattr_destroy");
|
||||
trace!("emscripten::_pthread_condattr_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_condattr_init");
|
||||
trace!("emscripten::_pthread_condattr_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_condattr_setclock");
|
||||
trace!("emscripten::_pthread_condattr_setclock");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_create");
|
||||
trace!("emscripten::_pthread_create");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_detach");
|
||||
trace!("emscripten::_pthread_detach");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_equal(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_equal");
|
||||
trace!("emscripten::_pthread_equal");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_exit(_ctx: &mut Ctx, _a: i32) -> () {
|
||||
debug!("emscripten::_pthread_exit");
|
||||
trace!("emscripten::_pthread_exit");
|
||||
}
|
||||
pub fn _pthread_getattr_np(_ctx: &mut Ctx, _thread: i32, _attr: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr);
|
||||
trace!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_getspecific");
|
||||
trace!("emscripten::_pthread_getspecific");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_join");
|
||||
trace!("emscripten::_pthread_join");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_key_create(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_key_create");
|
||||
trace!("emscripten::_pthread_key_create");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutex_destroy");
|
||||
trace!("emscripten::_pthread_mutex_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutex_init");
|
||||
trace!("emscripten::_pthread_mutex_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutexattr_destroy");
|
||||
trace!("emscripten::_pthread_mutexattr_destroy");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutexattr_init");
|
||||
trace!("emscripten::_pthread_mutexattr_init");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_mutexattr_settype");
|
||||
trace!("emscripten::_pthread_mutexattr_settype");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_once(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_once");
|
||||
trace!("emscripten::_pthread_once");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_destroy(_ctx: &mut Ctx, _rwlock: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_destroy({})", _rwlock);
|
||||
trace!("emscripten::_pthread_rwlock_destroy({})", _rwlock);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_init(_ctx: &mut Ctx, _rwlock: i32, _attr: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr);
|
||||
trace!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_rdlock");
|
||||
trace!("emscripten::_pthread_rwlock_rdlock");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_unlock");
|
||||
trace!("emscripten::_pthread_rwlock_unlock");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_rwlock_wrlock(_ctx: &mut Ctx, _rwlock: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_rwlock_wrlock({})", _rwlock);
|
||||
trace!("emscripten::_pthread_rwlock_wrlock({})", _rwlock);
|
||||
0
|
||||
}
|
||||
pub fn _pthread_setcancelstate(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_setcancelstate");
|
||||
trace!("emscripten::_pthread_setcancelstate");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_setspecific");
|
||||
trace!("emscripten::_pthread_setspecific");
|
||||
0
|
||||
}
|
||||
pub fn _pthread_sigmask(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
|
||||
debug!("emscripten::_pthread_sigmask");
|
||||
trace!("emscripten::_pthread_sigmask");
|
||||
0
|
||||
}
|
||||
pub fn ___gxx_personality_v0(
|
||||
@ -233,11 +233,6 @@ pub fn ___gxx_personality_v0(
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _gai_strerror(_ctx: &mut Ctx, _ecode: i32) -> i32 {
|
||||
debug!("emscripten::_gai_strerror({})", _ecode);
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 {
|
||||
debug!("emscripten::getdtablesize");
|
||||
|
50
lib/emscripten/src/env/mod.rs
vendored
50
lib/emscripten/src/env/mod.rs
vendored
@ -13,18 +13,22 @@ pub use self::windows::*;
|
||||
use libc::c_char;
|
||||
|
||||
use crate::{allocate_on_stack, EmscriptenData};
|
||||
use std::os::raw::c_int;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
pub fn _getaddrinfo(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32, _four: i32) -> i32 {
|
||||
debug!("emscripten::_getaddrinfo");
|
||||
-1
|
||||
}
|
||||
use std::os::raw::c_int;
|
||||
use wasmer_runtime_core::{
|
||||
memory::ptr::{Array, WasmPtr},
|
||||
types::ValueType,
|
||||
vm::Ctx,
|
||||
};
|
||||
|
||||
pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 {
|
||||
get_emscripten_data(ctx).malloc.call(size).unwrap()
|
||||
}
|
||||
|
||||
pub fn call_malloc_with_cast<T: Copy, Ty>(ctx: &mut Ctx, size: u32) -> WasmPtr<T, Ty> {
|
||||
WasmPtr::new(get_emscripten_data(ctx).malloc.call(size).unwrap())
|
||||
}
|
||||
|
||||
pub fn call_memalign(ctx: &mut Ctx, alignment: u32, size: u32) -> u32 {
|
||||
if let Some(memalign) = &get_emscripten_data(ctx).memalign {
|
||||
memalign.call(alignment, size).unwrap()
|
||||
@ -152,3 +156,37 @@ pub fn _fpathconf(_ctx: &mut Ctx, _fildes: c_int, name: c_int) -> c_int {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct EmAddrInfo {
|
||||
// int
|
||||
pub ai_flags: i32,
|
||||
// int
|
||||
pub ai_family: i32,
|
||||
// int
|
||||
pub ai_socktype: i32,
|
||||
// int
|
||||
pub ai_protocol: i32,
|
||||
// socklen_t
|
||||
pub ai_addrlen: u32,
|
||||
// struct sockaddr*
|
||||
pub ai_addr: WasmPtr<EmSockAddr>,
|
||||
// char*
|
||||
pub ai_canonname: WasmPtr<c_char, Array>,
|
||||
// struct addrinfo*
|
||||
pub ai_next: WasmPtr<EmAddrInfo>,
|
||||
}
|
||||
|
||||
unsafe impl ValueType for EmAddrInfo {}
|
||||
|
||||
// NOTE: from looking at emscripten JS, this should be a union
|
||||
// TODO: review this, highly likely to have bugs
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct EmSockAddr {
|
||||
pub sa_family: i16,
|
||||
pub sa_data: [c_char; 14],
|
||||
}
|
||||
|
||||
unsafe impl ValueType for EmSockAddr {}
|
||||
|
184
lib/emscripten/src/env/unix/mod.rs
vendored
184
lib/emscripten/src/env/unix/mod.rs
vendored
@ -3,13 +3,17 @@ use libc::{
|
||||
c_int, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv, sysconf,
|
||||
unsetenv,
|
||||
};
|
||||
use std::cell::Cell;
|
||||
use std::ffi::CStr;
|
||||
use std::mem;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use crate::env::call_malloc;
|
||||
use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr};
|
||||
use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
use wasmer_runtime_core::{
|
||||
memory::ptr::{Array, WasmPtr},
|
||||
vm::Ctx,
|
||||
};
|
||||
|
||||
// #[no_mangle]
|
||||
/// emscripten: _getenv // (name: *const char) -> *const c_char;
|
||||
@ -140,3 +144,179 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> i32 {
|
||||
// TODO: Implement like emscripten expects regarding memory/page size
|
||||
unsafe { sysconf(name) as i32 } // TODO review i64
|
||||
}
|
||||
|
||||
// this may be a memory leak, probably not though because emscripten does the same thing
|
||||
pub fn _gai_strerror(ctx: &mut Ctx, ecode: i32) -> i32 {
|
||||
debug!("emscripten::_gai_strerror({})", ecode);
|
||||
|
||||
let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) };
|
||||
let bytes = cstr.to_bytes_with_nul();
|
||||
let string_on_guest: WasmPtr<c_char, Array> = call_malloc_with_cast(ctx, bytes.len() as _);
|
||||
|
||||
let writer = unsafe {
|
||||
string_on_guest
|
||||
.deref_mut(ctx.memory(0), 0, bytes.len() as _)
|
||||
.unwrap()
|
||||
};
|
||||
for (i, byte) in bytes.iter().enumerate() {
|
||||
writer[i].set(*byte as i8);
|
||||
}
|
||||
|
||||
string_on_guest.offset() as _
|
||||
}
|
||||
|
||||
pub fn _getaddrinfo(
|
||||
ctx: &mut Ctx,
|
||||
node_ptr: WasmPtr<c_char>,
|
||||
service_str_ptr: WasmPtr<c_char>,
|
||||
hints_ptr: WasmPtr<EmAddrInfo>,
|
||||
res_val_ptr: WasmPtr<WasmPtr<EmAddrInfo>>,
|
||||
) -> i32 {
|
||||
use libc::{addrinfo, freeaddrinfo};
|
||||
debug!("emscripten::_getaddrinfo");
|
||||
let memory = ctx.memory(0);
|
||||
debug!(" => node = {}", unsafe {
|
||||
node_ptr
|
||||
.deref(memory)
|
||||
.map(|np| {
|
||||
std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
|
||||
.to_string_lossy()
|
||||
})
|
||||
.unwrap_or(std::borrow::Cow::Borrowed("null"))
|
||||
});
|
||||
debug!(" => server_str = {}", unsafe {
|
||||
service_str_ptr
|
||||
.deref(memory)
|
||||
.map(|np| {
|
||||
std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
|
||||
.to_string_lossy()
|
||||
})
|
||||
.unwrap_or(std::borrow::Cow::Borrowed("null"))
|
||||
});
|
||||
|
||||
let hints = hints_ptr.deref(memory).map(|hints_memory| {
|
||||
let hints_guest = hints_memory.get();
|
||||
unsafe {
|
||||
let mut hints_native: addrinfo = std::mem::uninitialized();
|
||||
hints_native.ai_flags = hints_guest.ai_flags;
|
||||
hints_native.ai_family = hints_guest.ai_family;
|
||||
hints_native.ai_socktype = hints_guest.ai_socktype;
|
||||
hints_native.ai_protocol = hints_guest.ai_protocol;
|
||||
hints_native.ai_addrlen = 0;
|
||||
hints_native.ai_addr = std::ptr::null_mut();
|
||||
hints_native.ai_canonname = std::ptr::null_mut();
|
||||
hints_native.ai_next = std::ptr::null_mut();
|
||||
|
||||
hints_native
|
||||
}
|
||||
});
|
||||
|
||||
let mut out_ptr: *mut addrinfo = std::ptr::null_mut();
|
||||
|
||||
// allocate equivalent memory for res_val_ptr
|
||||
let result = unsafe {
|
||||
libc::getaddrinfo(
|
||||
(node_ptr
|
||||
.deref(memory)
|
||||
.map(|m| m as *const Cell<c_char> as *const c_char))
|
||||
.unwrap_or(std::ptr::null()),
|
||||
(service_str_ptr
|
||||
.deref(memory)
|
||||
.map(|m| m as *const Cell<c_char> as *const c_char))
|
||||
.unwrap_or(std::ptr::null()),
|
||||
hints
|
||||
.as_ref()
|
||||
.map(|h| h as *const addrinfo)
|
||||
.unwrap_or(std::ptr::null()),
|
||||
&mut out_ptr as *mut *mut addrinfo,
|
||||
)
|
||||
};
|
||||
if result != 0 {
|
||||
return result;
|
||||
}
|
||||
|
||||
// walk linked list and copy over, freeing them from the kernel
|
||||
let head_of_list = unsafe {
|
||||
let mut current_host_node = out_ptr;
|
||||
let mut head_of_list = None;
|
||||
let mut previous_guest_node: Option<WasmPtr<EmAddrInfo>> = None;
|
||||
|
||||
while !current_host_node.is_null() {
|
||||
let current_guest_node_ptr: WasmPtr<EmAddrInfo> =
|
||||
call_malloc_with_cast(ctx, std::mem::size_of::<EmAddrInfo>() as _);
|
||||
if head_of_list.is_none() {
|
||||
head_of_list = Some(current_guest_node_ptr);
|
||||
}
|
||||
|
||||
// connect list
|
||||
if let Some(prev_guest) = previous_guest_node {
|
||||
let mut pg = prev_guest.deref_mut(ctx.memory(0)).unwrap().get_mut();
|
||||
pg.ai_next = current_guest_node_ptr;
|
||||
}
|
||||
|
||||
// update values
|
||||
|
||||
let host_addrlen = (*current_host_node).ai_addrlen;
|
||||
// allocate addr and copy data
|
||||
let guest_sockaddr_ptr = {
|
||||
let host_sockaddr_ptr = (*current_host_node).ai_addr;
|
||||
let guest_sockaddr_ptr: WasmPtr<EmSockAddr> =
|
||||
call_malloc_with_cast(ctx, host_addrlen as _);
|
||||
let guest_sockaddr = guest_sockaddr_ptr
|
||||
.deref_mut(ctx.memory(0))
|
||||
.unwrap()
|
||||
.get_mut();
|
||||
|
||||
guest_sockaddr.sa_family = (*host_sockaddr_ptr).sa_family as i16;
|
||||
guest_sockaddr.sa_data = (*host_sockaddr_ptr).sa_data.clone();
|
||||
guest_sockaddr_ptr
|
||||
};
|
||||
|
||||
// allocate canon name on guest and copy data over
|
||||
let guest_canonname_ptr = {
|
||||
let str_ptr = (*current_host_node).ai_canonname;
|
||||
if !str_ptr.is_null() {
|
||||
let canonname_cstr = std::ffi::CStr::from_ptr(str_ptr);
|
||||
let canonname_bytes = canonname_cstr.to_bytes_with_nul();
|
||||
let str_size = canonname_bytes.len();
|
||||
let guest_canonname: WasmPtr<c_char, Array> =
|
||||
call_malloc_with_cast(ctx, str_size as _);
|
||||
|
||||
let guest_canonname_writer = guest_canonname
|
||||
.deref(ctx.memory(0), 0, str_size as _)
|
||||
.unwrap();
|
||||
for (i, b) in canonname_bytes.into_iter().enumerate() {
|
||||
guest_canonname_writer[i].set(*b as i8)
|
||||
}
|
||||
|
||||
guest_canonname
|
||||
} else {
|
||||
WasmPtr::new(0)
|
||||
}
|
||||
};
|
||||
|
||||
let mut current_guest_node = current_guest_node_ptr
|
||||
.deref_mut(ctx.memory(0))
|
||||
.unwrap()
|
||||
.get_mut();
|
||||
current_guest_node.ai_flags = (*current_host_node).ai_flags;
|
||||
current_guest_node.ai_family = (*current_host_node).ai_family;
|
||||
current_guest_node.ai_socktype = (*current_host_node).ai_socktype;
|
||||
current_guest_node.ai_protocol = (*current_host_node).ai_protocol;
|
||||
current_guest_node.ai_addrlen = host_addrlen;
|
||||
current_guest_node.ai_addr = guest_sockaddr_ptr;
|
||||
current_guest_node.ai_canonname = guest_canonname_ptr;
|
||||
current_guest_node.ai_next = WasmPtr::new(0);
|
||||
|
||||
previous_guest_node = Some(current_guest_node_ptr);
|
||||
current_host_node = (*current_host_node).ai_next;
|
||||
}
|
||||
// this frees all connected nodes on the linked list
|
||||
freeaddrinfo(out_ptr);
|
||||
head_of_list.unwrap_or(WasmPtr::new(0))
|
||||
};
|
||||
|
||||
res_val_ptr.deref(ctx.memory(0)).unwrap().set(head_of_list);
|
||||
|
||||
0
|
||||
}
|
||||
|
20
lib/emscripten/src/env/windows/mod.rs
vendored
20
lib/emscripten/src/env/windows/mod.rs
vendored
@ -5,9 +5,9 @@ use std::ffi::CString;
|
||||
use std::mem;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use crate::env::call_malloc;
|
||||
use crate::env::{call_malloc, EmAddrInfo};
|
||||
use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm};
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx};
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "_putenv"]
|
||||
@ -131,3 +131,19 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long {
|
||||
// stub because sysconf is not valid on windows
|
||||
0
|
||||
}
|
||||
|
||||
pub fn _gai_strerror(_ctx: &mut Ctx, _ecode: i32) -> i32 {
|
||||
debug!("emscripten::_gai_strerror({}) - stub", _ecode);
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn _getaddrinfo(
|
||||
_ctx: &mut Ctx,
|
||||
_node_ptr: WasmPtr<c_char>,
|
||||
_service_str_ptr: WasmPtr<c_char>,
|
||||
_hints_ptr: WasmPtr<EmAddrInfo>,
|
||||
_res_val_ptr: WasmPtr<WasmPtr<EmAddrInfo>>,
|
||||
) -> i32 {
|
||||
debug!("emscripten::_getaddrinfo -- stub");
|
||||
-1
|
||||
}
|
||||
|
@ -893,7 +893,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
|
||||
"_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific),
|
||||
"_pthread_sigmask" => func!(crate::emscripten_target::_pthread_sigmask),
|
||||
"___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0),
|
||||
"_gai_strerror" => func!(crate::emscripten_target::_gai_strerror),
|
||||
"_gai_strerror" => func!(crate::env::_gai_strerror),
|
||||
"_getdtablesize" => func!(crate::emscripten_target::_getdtablesize),
|
||||
"_gethostbyaddr" => func!(crate::emscripten_target::_gethostbyaddr),
|
||||
"_gethostbyname" => func!(crate::emscripten_target::_gethostbyname),
|
||||
|
@ -434,6 +434,9 @@ pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
|
||||
}
|
||||
}
|
||||
|
||||
const SOCK_NON_BLOCK: i32 = 2048;
|
||||
const SOCK_CLOEXC: i32 = 0x80000;
|
||||
|
||||
// socketcall
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
|
||||
@ -467,13 +470,22 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
debug!("socket: socket");
|
||||
// socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int
|
||||
let domain: i32 = socket_varargs.get(ctx);
|
||||
let ty: i32 = socket_varargs.get(ctx);
|
||||
let ty_and_flags: i32 = socket_varargs.get(ctx);
|
||||
let protocol: i32 = socket_varargs.get(ctx);
|
||||
let ty = ty_and_flags & (!SOCK_NON_BLOCK) & (!SOCK_CLOEXC);
|
||||
let fd = unsafe { socket(domain, ty, protocol) };
|
||||
// set_cloexec
|
||||
unsafe {
|
||||
ioctl(fd, FIOCLEX);
|
||||
};
|
||||
|
||||
if ty_and_flags & SOCK_CLOEXC != 0 {
|
||||
// set_cloexec
|
||||
unsafe {
|
||||
ioctl(fd, FIOCLEX);
|
||||
};
|
||||
}
|
||||
|
||||
if ty_and_flags & SOCK_NON_BLOCK != 0 {
|
||||
// do something here
|
||||
unimplemented!("non blocking sockets");
|
||||
}
|
||||
|
||||
type T = u32;
|
||||
let payload = 1 as *const T as _;
|
||||
@ -642,18 +654,18 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
// 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);
|
||||
// SOL_SOCKET = 0xffff (BSD, Linux)
|
||||
let level: i32 = SOL_SOCKET;
|
||||
let _: u32 = socket_varargs.get(ctx);
|
||||
// SO_REUSEADDR = 0x4 (BSD, Linux)
|
||||
let name: i32 = SO_REUSEADDR;
|
||||
let _: u32 = 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 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 option_len = socket_varargs.get(ctx);
|
||||
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; // Endian problem
|
||||
let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
|
||||
|
||||
debug!("=> socketfd: {}, level: {} (SOL_SOCKET/0xffff), name: {} (SO_REUSEADDR/4), value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
|
||||
debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
|
||||
ret
|
||||
}
|
||||
15 => {
|
||||
|
@ -57,6 +57,18 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||
Some(&*cell_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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 {
|
||||
return None;
|
||||
}
|
||||
let cell_ptr = align_pointer(
|
||||
memory.view::<u8>().as_ptr().add(self.offset as usize) as usize,
|
||||
mem::align_of::<T>(),
|
||||
) as *mut Cell<T>;
|
||||
Some(&mut *cell_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
@ -81,6 +93,31 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
Some(cell_ptrs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn deref_mut<'a>(
|
||||
self,
|
||||
memory: &'a Memory,
|
||||
index: u32,
|
||||
length: u32,
|
||||
) -> Option<&'a mut [Cell<T>]> {
|
||||
// gets the size of the item in the array with padding added such that
|
||||
// for any index, we will always result an aligned memory access
|
||||
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;
|
||||
|
||||
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let cell_ptr = align_pointer(
|
||||
memory.view::<u8>().as_ptr().add(self.offset as usize) as usize,
|
||||
mem::align_of::<T>(),
|
||||
) as *mut Cell<T>;
|
||||
let cell_ptrs = &mut std::slice::from_raw_parts_mut(cell_ptr, slice_full_len)
|
||||
[index as usize..slice_full_len];
|
||||
Some(cell_ptrs)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Copy, Ty> WasmExternType for WasmPtr<T, Ty> {
|
||||
|
Reference in New Issue
Block a user