1 use core::ffi::c_void; 2 use std::io; 3 use std::os::unix::io::AsRawFd; 4 use std::os::unix::net::UnixStream; 5 6 use crate::Connection; 7 8 // TODO: Remove PeekExt once `gdbstub`'s MSRV >1.48 (rust-lang/rust#73761) 9 trait PeekExt { peek(&self, buf: &mut [u8]) -> io::Result<usize>10 fn peek(&self, buf: &mut [u8]) -> io::Result<usize>; 11 } 12 13 impl PeekExt for UnixStream { 14 #[allow(non_camel_case_types)] peek(&self, buf: &mut [u8]) -> io::Result<usize>15 fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { 16 // Define some libc types inline (to avoid bringing in entire libc dep) 17 18 // every platform supported by the libc crate uses c_int = i32 19 type c_int = i32; 20 type size_t = usize; 21 type ssize_t = isize; 22 const MSG_PEEK: c_int = 2; 23 extern "C" { 24 fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t; 25 } 26 27 // from std/sys/unix/mod.rs 28 pub fn cvt(t: isize) -> io::Result<isize> { 29 if t == -1 { 30 Err(io::Error::last_os_error()) 31 } else { 32 Ok(t) 33 } 34 } 35 36 // from std/sys/unix/net.rs 37 let ret = cvt(unsafe { 38 recv( 39 self.as_raw_fd(), 40 buf.as_mut_ptr() as *mut c_void, 41 buf.len(), 42 MSG_PEEK, 43 ) 44 })?; 45 Ok(ret as usize) 46 } 47 } 48 49 impl Connection for UnixStream { 50 type Error = std::io::Error; 51 read(&mut self) -> Result<u8, Self::Error>52 fn read(&mut self) -> Result<u8, Self::Error> { 53 use std::io::Read; 54 55 self.set_nonblocking(false)?; 56 57 let mut buf = [0u8]; 58 match Read::read_exact(self, &mut buf) { 59 Ok(_) => Ok(buf[0]), 60 Err(e) => Err(e), 61 } 62 } 63 read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>64 fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { 65 use std::io::Read; 66 67 self.set_nonblocking(false)?; 68 69 Read::read_exact(self, buf) 70 } 71 peek(&mut self) -> Result<Option<u8>, Self::Error>72 fn peek(&mut self) -> Result<Option<u8>, Self::Error> { 73 self.set_nonblocking(true)?; 74 75 let mut buf = [0u8]; 76 match PeekExt::peek(self, &mut buf) { 77 Ok(_) => Ok(Some(buf[0])), 78 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => Ok(None), 79 Err(e) => Err(e), 80 } 81 } 82 write(&mut self, byte: u8) -> Result<(), Self::Error>83 fn write(&mut self, byte: u8) -> Result<(), Self::Error> { 84 use std::io::Write; 85 86 Write::write_all(self, &[byte]) 87 } 88 write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>89 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 90 use std::io::Write; 91 92 Write::write_all(self, buf) 93 } 94 flush(&mut self) -> Result<(), Self::Error>95 fn flush(&mut self) -> Result<(), Self::Error> { 96 use std::io::Write; 97 98 Write::flush(self) 99 } 100 } 101