Skip to content

Commit 9647fce

Browse files
committed
Add some more socket methods + other misc fixes
1 parent 5ead286 commit 9647fce

File tree

4 files changed

+80
-23
lines changed

4 files changed

+80
-23
lines changed

Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,5 @@ opt-level = 3
6868

6969
[patch.crates-io]
7070
# REDOX START, Uncommment when you want to compile/check with redoxer
71-
# # following patches are just waiting on a new version to be released to crates.io
72-
# socket2 = { git = "https://github.com/alexcrichton/socket2-rs", branch = "v0.3.x" }
7371
# REDOX END
7472

vm/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ uname = "0.1.1"
106106
crc32fast = "1.2.0"
107107
adler32 = "1.0.3"
108108
gethostname = "0.2.0"
109-
socket2 = "0.3"
109+
socket2 = "0.3.19"
110110
rustyline = "6.0"
111111
openssl = { version = "0.10", features = ["vendored"], optional = true }
112112
openssl-sys = { version = "0.9", optional = true }

vm/src/py_io.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,25 @@ impl Write for PyWriter<'_> {
3030
}
3131
}
3232

33+
pub fn write_all(
34+
mut buf: &[u8],
35+
mut write: impl FnMut(&[u8]) -> io::Result<usize>,
36+
) -> io::Result<()> {
37+
while !buf.is_empty() {
38+
match write(buf) {
39+
Ok(0) => {
40+
return Err(io::Error::new(
41+
io::ErrorKind::WriteZero,
42+
"failed to write whole buffer",
43+
))
44+
}
45+
Ok(n) => buf = &buf[n..],
46+
Err(e) => return Err(e),
47+
}
48+
}
49+
Ok(())
50+
}
51+
3352
pub fn file_readline(obj: &PyObjectRef, size: Option<usize>, vm: &VirtualMachine) -> PyResult {
3453
let args = size.map_or_else(Vec::new, |size| vec![vm.ctx.new_int(size)]);
3554
let ret = vm.call_method(obj, "readline", args)?;

vm/src/stdlib/socket.rs

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use gethostname::gethostname;
44
use nix::unistd::sethostname;
55
use socket2::{Domain, Protocol, Socket, Type as SocketType};
66
use std::convert::TryFrom;
7-
use std::io::{self, prelude::*};
7+
use std::io;
88
use std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
99
use std::time::Duration;
1010

@@ -20,7 +20,7 @@ use crate::pyobject::{
2020
BorrowValue, Either, IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue,
2121
StaticType, TryFromObject,
2222
};
23-
use crate::vm::VirtualMachine;
23+
use crate::{py_io, VirtualMachine};
2424

2525
#[cfg(unix)]
2626
type RawSocket = std::os::unix::io::RawFd;
@@ -48,7 +48,8 @@ mod c {
4848
pub use winapi::shared::ws2def::*;
4949
pub use winapi::um::winsock2::{
5050
SD_BOTH as SHUT_RDWR, SD_RECEIVE as SHUT_RD, SD_SEND as SHUT_WR, SOCK_DGRAM, SOCK_RAW,
51-
SOCK_RDM, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_REUSEADDR, SO_TYPE, *,
51+
SOCK_RDM, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_ERROR, SO_OOBINLINE, SO_REUSEADDR,
52+
SO_TYPE, *,
5253
};
5354
}
5455

@@ -71,7 +72,7 @@ pub type PySocketRef = PyRef<PySocket>;
7172

7273
#[pyimpl(flags(BASETYPE))]
7374
impl PySocket {
74-
fn sock(&self) -> PyRwLockReadGuard<'_, Socket> {
75+
pub fn sock(&self) -> PyRwLockReadGuard<'_, Socket> {
7576
self.sock.read()
7677
}
7778

@@ -167,52 +168,90 @@ impl PySocket {
167168
}
168169

169170
#[pymethod]
170-
fn recv(&self, bufsize: usize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
171+
fn recv(
172+
&self,
173+
bufsize: usize,
174+
flags: OptionalArg<i32>,
175+
vm: &VirtualMachine,
176+
) -> PyResult<Vec<u8>> {
177+
let flags = flags.unwrap_or(0);
171178
let mut buffer = vec![0u8; bufsize];
172179
let n = self
173180
.sock()
174-
.recv(&mut buffer)
181+
.recv_with_flags(&mut buffer, flags)
175182
.map_err(|err| convert_sock_error(vm, err))?;
176183
buffer.truncate(n);
177184
Ok(buffer)
178185
}
179186

180187
#[pymethod]
181-
fn recv_into(&self, buf: PyRwBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
182-
buf.with_ref(|buf| self.sock().recv(buf))
188+
fn recv_into(
189+
&self,
190+
buf: PyRwBytesLike,
191+
flags: OptionalArg<i32>,
192+
vm: &VirtualMachine,
193+
) -> PyResult<usize> {
194+
let flags = flags.unwrap_or(0);
195+
buf.with_ref(|buf| self.sock().recv_with_flags(buf, flags))
183196
.map_err(|err| convert_sock_error(vm, err))
184197
}
185198

186199
#[pymethod]
187-
fn recvfrom(&self, bufsize: usize, vm: &VirtualMachine) -> PyResult<(Vec<u8>, AddrTuple)> {
200+
fn recvfrom(
201+
&self,
202+
bufsize: usize,
203+
flags: OptionalArg<i32>,
204+
vm: &VirtualMachine,
205+
) -> PyResult<(Vec<u8>, AddrTuple)> {
206+
let flags = flags.unwrap_or(0);
188207
let mut buffer = vec![0u8; bufsize];
189208
let (n, addr) = self
190209
.sock()
191-
.recv_from(&mut buffer)
210+
.recv_from_with_flags(&mut buffer, flags)
192211
.map_err(|err| convert_sock_error(vm, err))?;
193212
buffer.truncate(n);
194213
Ok((buffer, get_addr_tuple(addr)))
195214
}
196215

197216
#[pymethod]
198-
fn send(&self, bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
217+
fn send(
218+
&self,
219+
bytes: PyBytesLike,
220+
flags: OptionalArg<i32>,
221+
vm: &VirtualMachine,
222+
) -> PyResult<usize> {
223+
let flags = flags.unwrap_or(0);
199224
bytes
200-
.with_ref(|b| self.sock().send(b))
225+
.with_ref(|b| self.sock().send_with_flags(b, flags))
201226
.map_err(|err| convert_sock_error(vm, err))
202227
}
203228

204229
#[pymethod]
205-
fn sendall(&self, bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<()> {
230+
fn sendall(
231+
&self,
232+
bytes: PyBytesLike,
233+
flags: OptionalArg<i32>,
234+
vm: &VirtualMachine,
235+
) -> PyResult<()> {
236+
let flags = flags.unwrap_or(0);
237+
let sock = self.sock();
206238
bytes
207-
.with_ref(|b| self.sock_mut().write_all(b))
239+
.with_ref(|buf| py_io::write_all(buf, |b| sock.send_with_flags(b, flags)))
208240
.map_err(|err| convert_sock_error(vm, err))
209241
}
210242

211243
#[pymethod]
212-
fn sendto(&self, bytes: PyBytesLike, address: Address, vm: &VirtualMachine) -> PyResult<()> {
244+
fn sendto(
245+
&self,
246+
bytes: PyBytesLike,
247+
address: Address,
248+
flags: OptionalArg<i32>,
249+
vm: &VirtualMachine,
250+
) -> PyResult<()> {
251+
let flags = flags.unwrap_or(0);
213252
let addr = get_addr(vm, address, Some(self.family.load()))?;
214253
bytes
215-
.with_ref(|b| self.sock().send_to(b, &addr))
254+
.with_ref(|b| self.sock().send_to_with_flags(b, &addr, flags))
216255
.map_err(|err| convert_sock_error(vm, err))?;
217256
Ok(())
218257
}
@@ -411,15 +450,15 @@ impl PySocket {
411450

412451
impl io::Read for PySocketRef {
413452
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
414-
<Socket as io::Read>::read(&mut self.sock_mut(), buf)
453+
<&Socket as io::Read>::read(&mut &*self.sock(), buf)
415454
}
416455
}
417456
impl io::Write for PySocketRef {
418457
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
419-
<Socket as io::Write>::write(&mut self.sock_mut(), buf)
458+
<&Socket as io::Write>::write(&mut &*self.sock(), buf)
420459
}
421460
fn flush(&mut self) -> io::Result<()> {
422-
<Socket as io::Write>::flush(&mut self.sock_mut())
461+
<&Socket as io::Write>::flush(&mut &*self.sock())
423462
}
424463
}
425464

@@ -850,7 +889,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
850889
"SO_REUSEADDR" => ctx.new_int(c::SO_REUSEADDR),
851890
"SO_TYPE" => ctx.new_int(c::SO_TYPE),
852891
"SO_BROADCAST" => ctx.new_int(c::SO_BROADCAST),
853-
// "SO_EXCLUSIVEADDRUSE" => ctx.new_int(c::SO_EXCLUSIVEADDRUSE),
892+
"SO_OOBINLINE" => ctx.new_int(c::SO_OOBINLINE),
893+
"SO_ERROR" => ctx.new_int(c::SO_ERROR),
854894
"TCP_NODELAY" => ctx.new_int(c::TCP_NODELAY),
855895
"AI_ALL" => ctx.new_int(c::AI_ALL),
856896
"AI_PASSIVE" => ctx.new_int(c::AI_PASSIVE),

0 commit comments

Comments
 (0)