1
1
mirror of https://github.com/wez/wezterm.git synced 2024-08-17 02:00:25 +03:00

fixup windows impl

This commit is contained in:
Wez Furlong 2019-06-18 09:20:17 -07:00
parent 9ff22f9c09
commit ea0d3a0ed1

View File

@ -6,14 +6,22 @@ use failure::{bail, Fallible};
use std::io::{self, Error as IoError};
use std::os::windows::prelude::*;
use std::ptr;
use std::sync::Once;
use std::time::Duration;
use winapi::shared::ws2def::AF_INET;
use winapi::shared::ws2def::INADDR_LOOPBACK;
use winapi::shared::ws2def::SOCKADDR_IN;
use winapi::um::fileapi::*;
use winapi::um::handleapi::*;
use winapi::um::minwinbase::SECURITY_ATTRIBUTES;
use winapi::um::namedpipeapi::CreatePipe;
use winapi::um::namedpipeapi::{CreatePipe, GetNamedPipeInfo};
use winapi::um::processthreadsapi::*;
use winapi::um::winbase::{FILE_TYPE_CHAR, FILE_TYPE_DISK, FILE_TYPE_PIPE};
use winapi::um::winnt::HANDLE;
use winapi::um::winsock2::{closesocket, WSAPoll};
use winapi::um::winsock2::{
accept, bind, closesocket, connect, getsockname, htonl, listen, WSAPoll, WSASocketW,
WSAStartup, INVALID_SOCKET, SOCK_STREAM, WSADATA, WSA_FLAG_NO_HANDLE_INHERIT,
};
pub use winapi::um::winsock2::{POLLERR, POLLHUP, POLLIN, POLLOUT, WSAPOLLFD as pollfd};
/// `RawFileDescriptor` is a platform independent type alias for the
@ -41,6 +49,7 @@ impl<T: FromRawHandle> FromRawFileDescriptor for T {
unsafe impl Send for OwnedHandle {}
#[derive(Clone, Copy, PartialEq, Eq)]
enum HandleType {
Char,
Disk,
@ -50,7 +59,7 @@ enum HandleType {
}
fn handle_type(handle: HANDLE) -> HandleType {
match GetFileType(handle) {
match unsafe { GetFileType(handle) } {
FILE_TYPE_CHAR => HandleType::Char,
FILE_TYPE_DISK => HandleType::Disk,
FILE_TYPE_PIPE => {
@ -59,7 +68,9 @@ fn handle_type(handle: HANDLE) -> HandleType {
let mut out_buf = 0;
let mut in_buf = 0;
let mut inst = 0;
if GetNamedPipeInfo(handle, &mut flags, &mut out_buf, &mut in_buf, &mut inst) {
if unsafe { GetNamedPipeInfo(handle, &mut flags, &mut out_buf, &mut in_buf, &mut inst) }
!= 0
{
HandleType::Pipe
} else {
HandleType::Socket
@ -233,7 +244,7 @@ impl Pipe {
fn init_winsock() {
static START: Once = Once::new();
START.call_once(|| unsafe {
let mut data: WSADATA = mem::zeroed();
let mut data: WSADATA = std::mem::zeroed();
let ret = WSAStartup(
0x202, // version 2.2
&mut data,
@ -242,10 +253,91 @@ fn init_winsock() {
});
}
fn socket(af: i32, sock_type: i32, proto: i32) -> Fallible<FileDescriptor> {
let s = unsafe {
WSASocketW(
af,
sock_type,
proto,
ptr::null_mut(),
0,
WSA_FLAG_NO_HANDLE_INHERIT,
)
};
if s == INVALID_SOCKET {
bail!("socket failed: {}", IoError::last_os_error());
}
Ok(FileDescriptor {
handle: OwnedHandle { handle: s as _ },
})
}
#[doc(hidden)]
pub fn socketpair_impl() -> Fallible<(FileDescriptor, FileDescriptor)> {
init_winsock();
bail!("not implemented yet");
let s = socket(AF_INET, SOCK_STREAM, 0)?;
let mut in_addr: SOCKADDR_IN = unsafe { std::mem::zeroed() };
in_addr.sin_family = AF_INET as _;
unsafe {
*in_addr.sin_addr.S_un.S_addr_mut() = htonl(INADDR_LOOPBACK);
}
unsafe {
if bind(
s.as_raw_handle() as _,
std::mem::transmute(&in_addr),
std::mem::size_of_val(&in_addr) as _,
) != 0
{
bail!("bind failed: {}", IoError::last_os_error());
}
}
let mut addr_len = std::mem::size_of_val(&in_addr) as i32;
unsafe {
if getsockname(
s.as_raw_handle() as _,
std::mem::transmute(&mut in_addr),
&mut addr_len,
) != 0
{
bail!("getsockname failed: {}", IoError::last_os_error());
}
}
unsafe {
if listen(s.as_raw_handle() as _, 1) != 0 {
bail!("listen failed: {}", IoError::last_os_error());
}
}
let client = socket(AF_INET, SOCK_STREAM, 0)?;
unsafe {
if connect(
client.as_raw_handle() as _,
std::mem::transmute(&in_addr),
addr_len,
) != 0
{
bail!("connect failed: {}", IoError::last_os_error());
}
}
let server = unsafe { accept(s.as_raw_handle() as _, ptr::null_mut(), ptr::null_mut()) };
if server == INVALID_SOCKET {
bail!("socket failed: {}", IoError::last_os_error());
}
let server = FileDescriptor {
handle: OwnedHandle {
handle: server as _,
},
};
Ok((server, client))
}
#[doc(hidden)]
@ -265,3 +357,17 @@ pub fn poll_impl(pfd: &mut [pollfd], duration: Option<Duration>) -> Fallible<usi
Ok(poll_result as usize)
}
}
#[cfg(test)]
mod test {
use std::io::{Read, Write};
#[test]
fn socketpair() {
let (mut a, mut b) = super::socketpair_impl().unwrap();
a.write(b"hello").unwrap();
let mut buf = [0u8; 5];
assert_eq!(b.read(&mut buf).unwrap(), 5);
assert_eq!(&buf, b"hello");
}
}