Skip to content

Commit a42e94b

Browse files
committed
Add socket.getsockopt, impl io::{Read,Write} for PySocketRef
1 parent 2893117 commit a42e94b

File tree

1 file changed

+64
-1
lines changed

1 file changed

+64
-1
lines changed

vm/src/stdlib/socket.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ mod c {
3737
pub use winapi::shared::ws2def::*;
3838
pub use winapi::um::winsock2::{
3939
SD_BOTH as SHUT_RDWR, SD_RECEIVE as SHUT_RD, SD_SEND as SHUT_WR, SOCK_DGRAM, SOCK_RAW,
40-
SOCK_RDM, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_REUSEADDR, *,
40+
SOCK_RDM, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_REUSEADDR, SO_TYPE, *,
4141
};
4242
}
4343

@@ -208,6 +208,10 @@ impl PySocket {
208208
fn close(&self) {
209209
self.sock.replace(invalid_sock());
210210
}
211+
#[pymethod]
212+
fn detach(&self) -> RawSocket {
213+
into_sock_fileno(self.sock.replace(invalid_sock()))
214+
}
211215

212216
#[pymethod]
213217
fn fileno(&self) -> RawSocket {
@@ -278,6 +282,50 @@ impl PySocket {
278282
Ok(())
279283
}
280284

285+
#[pymethod]
286+
fn getsockopt(
287+
&self,
288+
level: i32,
289+
name: i32,
290+
buflen: OptionalArg<i32>,
291+
vm: &VirtualMachine,
292+
) -> PyResult {
293+
let fd = sock_fileno(&self.sock()) as _;
294+
let buflen = buflen.unwrap_or(0);
295+
if buflen == 0 {
296+
let mut flag: libc::c_int = 0;
297+
let mut flagsize = std::mem::size_of::<libc::c_int>() as _;
298+
let ret = unsafe {
299+
c::getsockopt(
300+
fd,
301+
level,
302+
name,
303+
&mut flag as *mut libc::c_int as *mut _,
304+
&mut flagsize,
305+
)
306+
};
307+
if ret < 0 {
308+
Err(convert_sock_error(vm, io::Error::last_os_error()))
309+
} else {
310+
Ok(vm.new_int(flag))
311+
}
312+
} else {
313+
if buflen <= 0 || buflen > 1024 {
314+
return Err(vm.new_os_error("getsockopt buflen out of range".to_owned()));
315+
}
316+
let mut buf = vec![0u8; buflen as usize];
317+
let mut buflen = buflen as _;
318+
let ret =
319+
unsafe { c::getsockopt(fd, level, name, buf.as_mut_ptr() as *mut _, &mut buflen) };
320+
buf.truncate(buflen as usize);
321+
if ret < 0 {
322+
Err(convert_sock_error(vm, io::Error::last_os_error()))
323+
} else {
324+
Ok(vm.ctx.new_bytes(buf))
325+
}
326+
}
327+
}
328+
281329
#[pymethod]
282330
fn setsockopt(
283331
&self,
@@ -348,6 +396,20 @@ impl PySocket {
348396
}
349397
}
350398

399+
impl io::Read for PySocketRef {
400+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
401+
<Socket as io::Read>::read(&mut self.sock.borrow_mut(), buf)
402+
}
403+
}
404+
impl io::Write for PySocketRef {
405+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
406+
<Socket as io::Write>::write(&mut self.sock.borrow_mut(), buf)
407+
}
408+
fn flush(&mut self) -> io::Result<()> {
409+
<Socket as io::Write>::flush(&mut self.sock.borrow_mut())
410+
}
411+
}
412+
351413
struct Address {
352414
host: PyStringRef,
353415
port: u16,
@@ -609,6 +671,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
609671
"SO_REUSEADDR" => ctx.new_int(c::SO_REUSEADDR),
610672
"TCP_NODELAY" => ctx.new_int(c::TCP_NODELAY),
611673
"SO_BROADCAST" => ctx.new_int(c::SO_BROADCAST),
674+
"SO_TYPE" => ctx.new_int(c::SO_TYPE),
612675
});
613676

614677
#[cfg(not(target_os = "redox"))]

0 commit comments

Comments
 (0)