1use std::io::{Error, ErrorKind, Result};
 2
 3use windows::Win32::{
 4    Foundation::{HANDLE, HANDLE_FLAG_INHERIT, HANDLE_FLAGS, SetHandleInformation},
 5    Networking::WinSock::{
 6        AF_UNIX, SEND_RECV_FLAGS, SOCK_STREAM, SOCKADDR, SOCKET, WSA_FLAG_OVERLAPPED,
 7        WSAEWOULDBLOCK, WSASocketW, accept, closesocket, recv, send,
 8    },
 9};
10
11use crate::util::map_ret;
12
13pub struct UnixSocket(SOCKET);
14
15impl UnixSocket {
16    pub fn new() -> Result<Self> {
17        unsafe {
18            let raw = WSASocketW(AF_UNIX as _, SOCK_STREAM.0, 0, None, 0, WSA_FLAG_OVERLAPPED)?;
19            SetHandleInformation(
20                HANDLE(raw.0 as _),
21                HANDLE_FLAG_INHERIT.0,
22                HANDLE_FLAGS::default(),
23            )?;
24            Ok(Self(raw))
25        }
26    }
27
28    pub(crate) fn as_raw(&self) -> SOCKET {
29        self.0
30    }
31
32    pub fn accept(&self, storage: *mut SOCKADDR, len: &mut i32) -> Result<Self> {
33        match unsafe { accept(self.0, Some(storage), Some(len)) } {
34            Ok(sock) => Ok(Self(sock)),
35            Err(err) => {
36                let wsa_err = unsafe { windows::Win32::Networking::WinSock::WSAGetLastError().0 };
37                if wsa_err == WSAEWOULDBLOCK.0 {
38                    Err(Error::new(ErrorKind::WouldBlock, "accept would block"))
39                } else {
40                    Err(err.into())
41                }
42            }
43        }
44    }
45
46    pub(crate) fn recv(&self, buf: &mut [u8]) -> Result<usize> {
47        map_ret(unsafe { recv(self.0, buf, SEND_RECV_FLAGS::default()) })
48    }
49
50    pub(crate) fn send(&self, buf: &[u8]) -> Result<usize> {
51        map_ret(unsafe { send(self.0, buf, SEND_RECV_FLAGS::default()) })
52    }
53}
54
55impl Drop for UnixSocket {
56    fn drop(&mut self) {
57        unsafe { closesocket(self.0) };
58    }
59}