Merge pull request #1205 from Lynskylate/impl-socket-module

Extend Socket module
This commit is contained in:
Aviv Palivoda
2019-08-08 17:30:02 +03:00
committed by GitHub
6 changed files with 91 additions and 4 deletions

11
Cargo.lock generated
View File

@@ -417,6 +417,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"
@@ -1041,6 +1050,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)",
@@ -1924,6 +1934,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"

View File

@@ -115,3 +115,17 @@ 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("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")

View File

@@ -70,3 +70,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"

View File

@@ -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")]

View File

@@ -183,7 +183,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();

View File

@@ -2,7 +2,14 @@ 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::net::{Ipv4Addr, SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket};
#[cfg(unix)]
use nix::unistd::sethostname;
use gethostname::gethostname;
use byteorder::{BigEndian, ByteOrder};
use crate::obj::objbytes::PyBytesRef;
use crate::obj::objint::PyIntRef;
@@ -12,6 +19,8 @@ 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;
#[derive(Debug, Copy, Clone)]
@@ -372,6 +381,34 @@ fn get_addr_tuple(vm: &VirtualMachine, addr: SocketAddr) -> PyResult {
Ok(vm.ctx.new_tuple(vec![ip, port]))
}
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))
}
fn socket_inet_aton(ip_string: PyStringRef, vm: &VirtualMachine) -> PyResult {
ip_string
.as_str()
.parse::<Ipv4Addr>()
.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()))
}
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;
@@ -390,10 +427,31 @@ 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),
"inet_ntoa" => ctx.new_rustfunc(socket_inet_ntoa),
"gethostname" => ctx.new_rustfunc(socket_gethostname),
});
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, {
"sethostname" => ctx.new_rustfunc(socket_sethostname),
});
module
}