Skip to content

Commit 589d178

Browse files
committed
windows unix stream: bind accept
1 parent 7950f24 commit 589d178

File tree

6 files changed

+139
-2
lines changed

6 files changed

+139
-2
lines changed

library/std/src/os/windows/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub mod io;
3232
pub mod process;
3333
pub mod raw;
3434
pub mod thread;
35+
pub mod net;
3536

3637
/// A prelude for conveniently writing platform-specific code.
3738
///
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#![stable(feature = "rust1", since = "1.0.0")]
2+
3+
use crate::os::raw::{c_char, c_int};
4+
use crate::{io, mem};
5+
use crate::sys::c;
6+
use crate::path::Path;
7+
#[stable(feature = "rust1", since = "1.0.0")]
8+
pub fn sockaddr_un(path: &Path)->io::Result<(c::sockaddr_un,c_int)>{
9+
let mut addr: c::sockaddr_un = unsafe { mem::zeroed()};
10+
addr.sun_family = c::AF_UNIX;
11+
// Winsock2 expects 'sun_path' to be a Win32 UTF-8 file system path
12+
let bytes = path.to_str().map(|s| s.as_bytes()).ok_or(io::Error::new(
13+
io::ErrorKind::InvalidInput,
14+
"path contains invalid characters",
15+
))?;
16+
17+
if bytes.contains(&0) {
18+
return Err(io::Error::new(
19+
io::ErrorKind::InvalidInput,
20+
"paths may not contain interior null bytes",
21+
));
22+
}
23+
24+
if bytes.len() >= addr.sun_path.len() {
25+
return Err(io::Error::new(
26+
io::ErrorKind::InvalidInput,
27+
"path must be shorter than SUN_LEN",
28+
));
29+
}
30+
for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
31+
*dst = *src as c_char;
32+
}
33+
// null byte for pathname addresses is already there because we zeroed the
34+
// struct
35+
36+
let mut len = sun_path_offset(&addr) + bytes.len();
37+
match bytes.first() {
38+
Some(&0) | None => {}
39+
Some(_) => len += 1,
40+
}
41+
Ok((addr,len as _))
42+
}
43+
fn sun_path_offset(addr: &c::sockaddr_un) -> usize {
44+
// Work with an actual instance of the type since using a null pointer is UB
45+
let base = addr as *const _ as usize;
46+
let path = &addr.sun_path as *const _ as usize;
47+
path - base
48+
}
49+
#[stable(feature = "rust1", since = "1.0.0")]
50+
pub struct SocketAddr {
51+
addr: c::sockaddr_un,
52+
len: c_int,
53+
}
54+
impl SocketAddr {
55+
fn from_parts(addr: c::sockaddr_un, mut len: c_int) -> io::Result<SocketAddr> {
56+
if len == 0 {
57+
// When there is a datagram from unnamed unix socket
58+
// linux returns zero bytes of address
59+
len = sun_path_offset(&addr) as c_int; // i.e. zero-length address
60+
} else if addr.sun_family != c::AF_UNIX {
61+
return Err(io::Error::new(
62+
io::ErrorKind::InvalidInput,
63+
"file descriptor did not correspond to a Unix socket",
64+
));
65+
}
66+
67+
Ok(SocketAddr { addr, len })
68+
}
69+
}
70+
#[stable(feature = "rust1", since = "1.0.0")]
71+
pub fn from_sockaddr_un(addr: c::sockaddr_un, len: c_int) -> io::Result<SocketAddr> {
72+
SocketAddr::from_parts(addr, len)
73+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use core::mem;
2+
3+
use super::sockaddr_un;
4+
use crate::io;
5+
use crate::os::raw::c_int;
6+
use crate::os::windows::net::{SocketAddr, from_sockaddr_un};
7+
use crate::path::Path;
8+
use crate::sys::c::{self, bind, listen};
9+
use crate::sys::cvt;
10+
use crate::sys::net::Socket;
11+
#[stable(feature = "rust1", since = "1.0.0")]
12+
13+
pub struct UnixListener(Socket);
14+
#[stable(feature = "rust1", since = "1.0.0")]
15+
16+
pub struct UnixStream(Socket);
17+
impl UnixListener {
18+
#[stable(feature = "rust1", since = "1.0.0")]
19+
pub fn bind<P: AsRef<Path>>(path: &Path) -> io::Result<UnixListener> {
20+
unsafe {
21+
let inner = Socket::new_unix()?;
22+
let (addr, len) = sockaddr_un(path)?;
23+
cvt(bind(inner.as_raw(), &addr as *const _ as *const _, len))?;
24+
cvt(listen(inner.as_raw(), 128))?;
25+
Ok(UnixListener(inner))
26+
}
27+
}
28+
#[stable(feature = "rust1", since = "1.0.0")]
29+
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
30+
let mut storage: c::sockaddr_un = unsafe { mem::zeroed() };
31+
let mut len = mem::size_of_val(&storage) as c_int;
32+
let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?;
33+
let addr = from_sockaddr_un(storage, len)?;
34+
Ok((UnixStream(sock), addr))
35+
}
36+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![stable(feature = "rust1", since = "1.0.0")]
2+
3+
mod listener;
4+
mod addr;
5+
#[stable(feature = "rust1", since = "1.0.0")]
6+
pub use addr::*;
7+
#[stable(feature = "rust1", since = "1.0.0")]
8+
pub use listener::*;

library/std/src/sys/net/connection/socket/windows.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::os::windows::io::{
99
AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
1010
};
1111
use crate::sys::c;
12+
use crate::sys::c::{AF_UNIX, INVALID_SOCKET, SOCK_STREAM, WSA_FLAG_OVERLAPPED, WSASocketW};
1213
use crate::sys::pal::winsock::last_error;
1314
use crate::sys_common::{AsInner, FromInner, IntoInner};
1415
use crate::time::Duration;
@@ -28,7 +29,7 @@ pub(super) mod netc {
2829
use crate::sys::c::{self, ADDRESS_FAMILY, ADDRINFOA, SOCKADDR, SOCKET};
2930
// re-exports from Windows API bindings.
3031
pub use crate::sys::c::{
31-
ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, IP_ADD_MEMBERSHIP,
32+
ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, AF_UNIX, IP_ADD_MEMBERSHIP,
3233
IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, IPPROTO_IP, IPPROTO_IPV6,
3334
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, SO_BROADCAST,
3435
SO_RCVTIMEO, SO_SNDTIMEO, SOCK_DGRAM, SOCK_STREAM, SOCKADDR as sockaddr,
@@ -117,6 +118,16 @@ pub use crate::sys::pal::winsock::{cleanup, cvt, cvt_gai, cvt_r, startup as init
117118
pub struct Socket(OwnedSocket);
118119

119120
impl Socket {
121+
pub fn new_unix() -> io::Result<Socket> {
122+
let socket = unsafe {
123+
match WSASocketW(AF_UNIX as i32, SOCK_STREAM, 0, ptr::null_mut(), 0, WSA_FLAG_OVERLAPPED) {
124+
INVALID_SOCKET => Err(last_error()),
125+
n => Ok(Socket::from_raw(n)),
126+
}
127+
}?;
128+
socket.0.set_no_inherit();
129+
Ok(socket)
130+
}
120131
pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
121132
let family = match *addr {
122133
SocketAddr::V4(..) => netc::AF_INET,

library/std/src/sys/pal/windows/c.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,16 @@ use core::ptr;
1111
mod windows_sys;
1212
pub use windows_sys::*;
1313

14-
pub type WCHAR = u16;
14+
use crate::os::raw::c_char;
1515

16+
pub type WCHAR = u16;
17+
pub const AF_UNIX: u16 = 1;
18+
#[derive(Clone,Copy)]
19+
#[repr(C)]
20+
pub struct sockaddr_un {
21+
pub sun_family: ADDRESS_FAMILY,
22+
pub sun_path: [c_char; 108],
23+
}
1624
pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i32 as _);
1725

1826
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170

0 commit comments

Comments
 (0)