From 5f4c8c65faab7f72f6892483b55a1d08246bf1c8 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Mon, 5 Aug 2019 00:16:05 +0800 Subject: [PATCH 1/5] Impl gethostname sethostname inet_aton --- tests/snippets/stdlib_socket.py | 6 ++++++ vm/src/stdlib/os.rs | 2 +- vm/src/stdlib/socket.rs | 34 ++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/tests/snippets/stdlib_socket.py b/tests/snippets/stdlib_socket.py index d7afe1bd3..1b9a2408b 100644 --- a/tests/snippets/stdlib_socket.py +++ b/tests/snippets/stdlib_socket.py @@ -115,3 +115,9 @@ with assertRaises(OSError): with assertRaises(OSError): socket.socket(socket.AF_INET, 1000) + +with assertRaises(OSError) : + socket.inet_aton("test") + +assert socket.inet_aton("127.0.0.1")==b"\x7f\x00\x00\x01" +assert socket.inet_aton("127.0.0.1")==b"\xff\xff\xff\xff" diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 227edcab1..04ffe257a 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -182,7 +182,7 @@ fn convert_io_error(vm: &VirtualMachine, err: io::Error) -> PyObjectRef { } #[cfg(unix)] -fn convert_nix_error(vm: &VirtualMachine, err: nix::Error) -> PyObjectRef { +pub fn convert_nix_error(vm: &VirtualMachine, err: nix::Error) -> PyObjectRef { let nix_error = match err { nix::Error::InvalidPath => { let exc_type = vm.ctx.exceptions.file_not_found_error.clone(); diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 714c3e30c..774db9e23 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -2,7 +2,11 @@ use std::cell::RefCell; use std::io; use std::io::Read; use std::io::Write; -use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; +use std::mem::transmute; +use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; + +#[cfg(unix)] +use nix::unistd::{gethostname, sethostname}; use crate::obj::objbytes::PyBytesRef; use crate::obj::objint::PyIntRef; @@ -12,6 +16,7 @@ use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; use crate::vm::VirtualMachine; use crate::obj::objtype::PyClassRef; +use crate::stdlib::os::convert_nix_error; use num_traits::ToPrimitive; #[derive(Debug, Copy, Clone)] @@ -372,6 +377,30 @@ fn get_addr_tuple(vm: &VirtualMachine, addr: SocketAddr) -> PyResult { Ok(vm.ctx.new_tuple(vec![ip, port])) } +#[cfg(unix)] +fn socket_gethostname(vm: &VirtualMachine) -> PyObjectRef { + let mut buf = [0u8; 1024]; + match gethostname(&mut buf) { + Ok(cstr) => vm.new_str(String::from(cstr.to_str().unwrap())), + Err(e) => convert_nix_error(vm, e), + } +} + +#[cfg(unix)] +fn socket_sethostname(hostname: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { + sethostname(hostname.value.as_str()).map_err(|err| convert_nix_error(vm, err)) +} + +fn socket_inet_aton(ip_string: PyStringRef, vm: &VirtualMachine) -> PyResult { + match ip_string.as_str().parse::() { + Ok(ip_addr) => { + let out_bytes: [u8; 4] = unsafe { transmute(u32::from(ip_addr).to_be()) }; + Ok(vm.ctx.new_bytes(out_bytes.to_vec())) + } + Err(_) => Err(vm.new_os_error("illegal IP address string passed to inet_aton".to_string())), + } +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -395,5 +424,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "SOCK_STREAM" => ctx.new_int(SocketKind::Stream as i32), "SOCK_DGRAM" => ctx.new_int(SocketKind::Dgram as i32), "socket" => socket, + "gethostname" => ctx.new_rustfunc(socket_gethostname), + "sethostname" => ctx.new_rustfunc(socket_sethostname), + "inet_aton" => ctx.new_rustfunc(socket_inet_aton), }) } From 14c6b4028e853174971f216636df97b596a0ab84 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Mon, 5 Aug 2019 00:57:04 +0800 Subject: [PATCH 2/5] Specific platform --- vm/src/stdlib/socket.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 774db9e23..8dc17f185 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -16,6 +16,7 @@ use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; use crate::vm::VirtualMachine; use crate::obj::objtype::PyClassRef; +#[cfg(unix)] use crate::stdlib::os::convert_nix_error; use num_traits::ToPrimitive; @@ -419,13 +420,30 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "fileno" => ctx.new_rustfunc(SocketRef::fileno), }); - py_module!(vm, "socket", { + let module = py_module!(vm, "socket", { "AF_INET" => ctx.new_int(AddressFamily::Inet as i32), "SOCK_STREAM" => ctx.new_int(SocketKind::Stream as i32), "SOCK_DGRAM" => ctx.new_int(SocketKind::Dgram as i32), "socket" => socket, + "inet_aton" => ctx.new_rustfunc(socket_inet_aton), + }); + + extend_module_platform_specific(vm, module) +} + +#[cfg(not(unix))] +fn extend_module_platform_specific(_vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef { + module +} + +#[cfg(unix)] +fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) -> PyObjectRef { + let ctx = &vm.ctx; + + extend_module!(vm, module, { "gethostname" => ctx.new_rustfunc(socket_gethostname), "sethostname" => ctx.new_rustfunc(socket_sethostname), - "inet_aton" => ctx.new_rustfunc(socket_inet_aton), - }) + }); + + module } From 4e969e9db74628cbbf38235592beea78b83d3840 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Mon, 5 Aug 2019 07:10:28 +0800 Subject: [PATCH 3/5] Remove unsafe code --- tests/snippets/stdlib_socket.py | 2 +- vm/src/stdlib/socket.rs | 19 ++++++++----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/snippets/stdlib_socket.py b/tests/snippets/stdlib_socket.py index 1b9a2408b..8bd8bc204 100644 --- a/tests/snippets/stdlib_socket.py +++ b/tests/snippets/stdlib_socket.py @@ -120,4 +120,4 @@ with assertRaises(OSError) : socket.inet_aton("test") assert socket.inet_aton("127.0.0.1")==b"\x7f\x00\x00\x01" -assert socket.inet_aton("127.0.0.1")==b"\xff\xff\xff\xff" +assert socket.inet_aton("255.255.255.255")==b"\xff\xff\xff\xff" diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 8dc17f185..8775eb85d 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::io; use std::io::Read; use std::io::Write; -use std::mem::transmute; use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; #[cfg(unix)] @@ -379,11 +378,11 @@ fn get_addr_tuple(vm: &VirtualMachine, addr: SocketAddr) -> PyResult { } #[cfg(unix)] -fn socket_gethostname(vm: &VirtualMachine) -> PyObjectRef { +fn socket_gethostname(vm: &VirtualMachine) -> PyResult { let mut buf = [0u8; 1024]; match gethostname(&mut buf) { - Ok(cstr) => vm.new_str(String::from(cstr.to_str().unwrap())), - Err(e) => convert_nix_error(vm, e), + Ok(cstr) => Ok(vm.new_str(String::from(cstr.to_str().unwrap()))), + Err(e) => Err(convert_nix_error(vm, e)), } } @@ -393,13 +392,11 @@ fn socket_sethostname(hostname: PyStringRef, vm: &VirtualMachine) -> PyResult<() } fn socket_inet_aton(ip_string: PyStringRef, vm: &VirtualMachine) -> PyResult { - match ip_string.as_str().parse::() { - Ok(ip_addr) => { - let out_bytes: [u8; 4] = unsafe { transmute(u32::from(ip_addr).to_be()) }; - Ok(vm.ctx.new_bytes(out_bytes.to_vec())) - } - Err(_) => Err(vm.new_os_error("illegal IP address string passed to inet_aton".to_string())), - } + ip_string + .as_str() + .parse::() + .map(|ip_addr| vm.ctx.new_bytes(ip_addr.octets().to_vec())) + .map_err(|_| vm.new_os_error("illegal IP address string passed to inet_aton".to_string())) } pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { From c9c580d2fea324fa1e2f6e7aa741f728a2151036 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Wed, 7 Aug 2019 00:41:54 +0800 Subject: [PATCH 4/5] Add inet_ntoa and windows gethostname --- Cargo.lock | 11 +++++++++++ tests/snippets/stdlib_socket.py | 10 +++++++++- vm/Cargo.toml | 1 + vm/src/stdlib/socket.rs | 24 +++++++++++++++++++++++- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8ea01dc1..3124b83f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -398,6 +398,15 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gethostname" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heck" version = "0.3.1" @@ -1021,6 +1030,7 @@ dependencies = [ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1902,6 +1912,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4ab273ca2a31eb6ca40b15837ccf1aa59a43c5db69ac10c542be342fae2e01d" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79296f72d53a89096cbc9a88c9547ee8dfe793388674620e2207593d370550ac" diff --git a/tests/snippets/stdlib_socket.py b/tests/snippets/stdlib_socket.py index 8bd8bc204..581100c58 100644 --- a/tests/snippets/stdlib_socket.py +++ b/tests/snippets/stdlib_socket.py @@ -116,8 +116,16 @@ with assertRaises(OSError): with assertRaises(OSError): socket.socket(socket.AF_INET, 1000) -with assertRaises(OSError) : +with assertRaises(OSError): socket.inet_aton("test") assert socket.inet_aton("127.0.0.1")==b"\x7f\x00\x00\x01" assert socket.inet_aton("255.255.255.255")==b"\xff\xff\xff\xff" + + +assert socket.inet_ntoa(b"\x7f\x00\x00\x01")=="127.0.0.1" +assert socket.inet_ntoa(b"\xff\xff\xff\xff")=="255.255.255.255" + +with assertRaises(OSError): + socket.inet_ntoa(b"\xff\xff\xff\xff\xff") + diff --git a/vm/Cargo.toml b/vm/Cargo.toml index d4913b782..d5412bbe2 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -24,6 +24,7 @@ sha2 = "0.8" sha3 = "0.8" blake2 = "0.8" +gethostname = "0.2.0" num-complex = { version = "0.2", features = ["serde"] } num-bigint = { version = "0.2", features = ["serde"] } num-traits = "=0.2.6" diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 8775eb85d..e30bdd62e 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -7,6 +7,11 @@ use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpS #[cfg(unix)] use nix::unistd::{gethostname, sethostname}; +#[cfg(windows)] +use gethostname::gethostname; + +use byteorder::{BigEndian, ByteOrder}; + use crate::obj::objbytes::PyBytesRef; use crate::obj::objint::PyIntRef; use crate::obj::objstr::PyStringRef; @@ -386,6 +391,14 @@ fn socket_gethostname(vm: &VirtualMachine) -> PyResult { } } +#[cfg(windows)] +fn socket_gethostname(vm: &VirtualMachine) -> PyResult { + gethostname() + .into_string() + .map(|hostname| vm.new_str(hostname)) + .map_err(|err| vm.new_os_error(err.into_string().unwrap())) +} + #[cfg(unix)] fn socket_sethostname(hostname: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { sethostname(hostname.value.as_str()).map_err(|err| convert_nix_error(vm, err)) @@ -399,6 +412,14 @@ fn socket_inet_aton(ip_string: PyStringRef, vm: &VirtualMachine) -> PyResult { .map_err(|_| vm.new_os_error("illegal IP address string passed to inet_aton".to_string())) } +fn socket_inet_ntoa(packed_ip: PyBytesRef, vm: &VirtualMachine) -> PyResult { + if packed_ip.len() != 4 { + return Err(vm.new_os_error("packed IP wrong length for inet_ntoa".to_string())); + } + let ip_num = BigEndian::read_u32(packed_ip.get_value()); + Ok(vm.new_str(Ipv4Addr::from(ip_num).to_string())) +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -423,6 +444,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "SOCK_DGRAM" => ctx.new_int(SocketKind::Dgram as i32), "socket" => socket, "inet_aton" => ctx.new_rustfunc(socket_inet_aton), + "inet_ntoa" => ctx.new_rustfunc(socket_inet_ntoa), + "gethostname" => ctx.new_rustfunc(socket_gethostname), }); extend_module_platform_specific(vm, module) @@ -438,7 +461,6 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) -> let ctx = &vm.ctx; extend_module!(vm, module, { - "gethostname" => ctx.new_rustfunc(socket_gethostname), "sethostname" => ctx.new_rustfunc(socket_sethostname), }); From fccb0d2adedee314b2c00525f577a262e2497029 Mon Sep 17 00:00:00 2001 From: lynskylate Date: Wed, 7 Aug 2019 23:48:53 +0800 Subject: [PATCH 5/5] Disable socket import on wasm --- vm/Cargo.toml | 4 +++- vm/src/stdlib/mod.rs | 1 + vm/src/stdlib/socket.rs | 13 +------------ 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/vm/Cargo.toml b/vm/Cargo.toml index d5412bbe2..64b9134d5 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -24,7 +24,6 @@ sha2 = "0.8" sha3 = "0.8" blake2 = "0.8" -gethostname = "0.2.0" num-complex = { version = "0.2", features = ["serde"] } num-bigint = { version = "0.2", features = ["serde"] } num-traits = "=0.2.6" @@ -70,3 +69,6 @@ flamer = { version = "0.3", optional = true } [target.'cfg(all(unix, not(any(target_os = "android", target_os = "redox"))))'.dependencies] pwd = "1" + +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +gethostname = "0.2.0" diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index dea27dfe0..2637ade1e 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -17,6 +17,7 @@ mod platform; mod pystruct; mod random; mod re; +#[cfg(not(target_arch = "wasm32"))] pub mod socket; mod string; #[cfg(feature = "rustpython-compiler")] diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index e30bdd62e..22f431a82 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -5,9 +5,8 @@ use std::io::Write; use std::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; #[cfg(unix)] -use nix::unistd::{gethostname, sethostname}; +use nix::unistd::sethostname; -#[cfg(windows)] use gethostname::gethostname; use byteorder::{BigEndian, ByteOrder}; @@ -382,16 +381,6 @@ fn get_addr_tuple(vm: &VirtualMachine, addr: SocketAddr) -> PyResult { Ok(vm.ctx.new_tuple(vec![ip, port])) } -#[cfg(unix)] -fn socket_gethostname(vm: &VirtualMachine) -> PyResult { - let mut buf = [0u8; 1024]; - match gethostname(&mut buf) { - Ok(cstr) => Ok(vm.new_str(String::from(cstr.to_str().unwrap()))), - Err(e) => Err(convert_nix_error(vm, e)), - } -} - -#[cfg(windows)] fn socket_gethostname(vm: &VirtualMachine) -> PyResult { gethostname() .into_string()