1 use std
::io
::{Read, Write}
;
3 use std
::net
::Shutdown
;
4 use std
::os
::unix
::prelude
::*;
10 use {io, Ready, Poll, PollOpt, Token}
;
12 use sys
::unix
::{cvt, Io}
;
13 use sys
::unix
::io
::{set_nonblock, set_cloexec}
;
16 fn my_into(self) -> T
;
19 impl MyInto
<u32> for usize {
20 fn my_into(self) -> u32 { self as u32 }
23 impl MyInto
<usize> for usize {
24 fn my_into(self) -> usize { self }
27 unsafe fn sockaddr_un(path
: &Path
)
28 -> io
::Result
<(libc
::sockaddr_un
, libc
::socklen_t
)> {
29 let mut addr
: libc
::sockaddr_un
= mem
::zeroed();
30 addr
.sun_family
= libc
::AF_UNIX
as libc
::sa_family_t
;
32 let bytes
= path
.as_os_str().as_bytes();
34 if bytes
.len() >= addr
.sun_path
.len() {
35 return Err(io
::Error
::new(io
::ErrorKind
::InvalidInput
,
36 "path must be shorter than SUN_LEN"))
38 for (dst
, src
) in addr
.sun_path
.iter_mut().zip(bytes
.iter()) {
39 *dst
= *src
as libc
::c_char
;
41 // null byte for pathname addresses is already there because we zeroed the
44 let mut len
= sun_path_offset() + bytes
.len();
49 Ok((addr
, len
as libc
::socklen_t
))
52 fn sun_path_offset() -> usize {
54 // Work with an actual instance of the type since using a null pointer is UB
55 let addr
: libc
::sockaddr_un
= mem
::uninitialized();
56 let base
= &addr
as *const _
as usize;
57 let path
= &addr
.sun_path
as *const _
as usize;
63 pub struct UnixSocket
{
68 /// Returns a new, unbound, non-blocking Unix domain socket
69 pub fn stream() -> io
::Result
<UnixSocket
> {
70 #[cfg(target_os = "linux")]
71 use libc
::{SOCK_CLOEXEC, SOCK_NONBLOCK}
;
72 #[cfg(not(target_os = "linux"))]
73 const SOCK_CLOEXEC
: libc
::c_int
= 0;
74 #[cfg(not(target_os = "linux"))]
75 const SOCK_NONBLOCK
: libc
::c_int
= 0;
78 if cfg
!(target_os
= "linux") {
79 let flags
= libc
::SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
;
80 match cvt(libc
::socket(libc
::AF_UNIX
, flags
, 0)) {
81 Ok(fd
) => return Ok(UnixSocket
::from_raw_fd(fd
)),
82 Err(ref e
) if e
.raw_os_error() == Some(libc
::EINVAL
) => {}
83 Err(e
) => return Err(e
),
87 let fd
= cvt(libc
::socket(libc
::AF_UNIX
, libc
::SOCK_STREAM
, 0))?
;
88 let fd
= UnixSocket
::from_raw_fd(fd
);
89 set_cloexec(fd
.as_raw_fd())?
;
90 set_nonblock(fd
.as_raw_fd())?
;
95 /// Connect the socket to the specified address
96 pub fn connect
<P
: AsRef
<Path
> + ?Sized
>(&self, addr
: &P
) -> io
::Result
<()> {
98 let (addr
, len
) = sockaddr_un(addr
.as_ref())?
;
99 cvt(libc
::connect(self.as_raw_fd(),
100 &addr
as *const _
as *const _
,
106 /// Listen for incoming requests
107 pub fn listen(&self, backlog
: usize) -> io
::Result
<()> {
109 cvt(libc
::listen(self.as_raw_fd(), backlog
as i32))?
;
114 pub fn accept(&self) -> io
::Result
<UnixSocket
> {
116 let fd
= cvt(libc
::accept(self.as_raw_fd(),
119 let fd
= Io
::from_raw_fd(fd
);
120 set_cloexec(fd
.as_raw_fd())?
;
121 set_nonblock(fd
.as_raw_fd())?
;
122 Ok(UnixSocket { io: fd }
)
126 /// Bind the socket to the specified address
127 pub fn bind
<P
: AsRef
<Path
> + ?Sized
>(&self, addr
: &P
) -> io
::Result
<()> {
129 let (addr
, len
) = sockaddr_un(addr
.as_ref())?
;
130 cvt(libc
::bind(self.as_raw_fd(),
131 &addr
as *const _
as *const _
,
137 pub fn try_clone(&self) -> io
::Result
<UnixSocket
> {
138 Ok(UnixSocket { io: self.io.try_clone()? }
)
141 pub fn shutdown(&self, how
: Shutdown
) -> io
::Result
<()> {
142 let how
= match how
{
143 Shutdown
::Read
=> libc
::SHUT_RD
,
144 Shutdown
::Write
=> libc
::SHUT_WR
,
145 Shutdown
::Both
=> libc
::SHUT_RDWR
,
148 cvt(libc
::shutdown(self.as_raw_fd(), how
))?
;
153 pub fn read_recv_fd(&mut self, buf
: &mut [u8]) -> io
::Result
<(usize, Option
<RawFd
>)> {
155 let mut iov
= libc
::iovec
{
156 iov_base
: buf
.as_mut_ptr() as *mut _
,
161 data
: [libc
::c_int
; 1],
163 let mut cmsg
: Cmsg
= mem
::zeroed();
164 let mut msg
: libc
::msghdr
= mem
::zeroed();
165 msg
.msg_iov
= &mut iov
;
167 msg
.msg_control
= &mut cmsg
as *mut _
as *mut _
;
168 msg
.msg_controllen
= mem
::size_of_val(&cmsg
).my_into();
169 let bytes
= cvt(libc
::recvmsg(self.as_raw_fd(), &mut msg
, 0))?
;
171 const SCM_RIGHTS
: libc
::c_int
= 1;
173 let fd
= if cmsg
.hdr
.cmsg_level
== libc
::SOL_SOCKET
&&
174 cmsg
.hdr
.cmsg_type
== SCM_RIGHTS
{
179 Ok((bytes
as usize, fd
))
183 pub fn write_send_fd(&mut self, buf
: &[u8], fd
: RawFd
) -> io
::Result
<usize> {
185 let mut iov
= libc
::iovec
{
186 iov_base
: buf
.as_ptr() as *mut _
,
191 data
: [libc
::c_int
; 1],
193 let mut cmsg
: Cmsg
= mem
::zeroed();
194 cmsg
.hdr
.cmsg_len
= mem
::size_of_val(&cmsg
).my_into();
195 cmsg
.hdr
.cmsg_level
= libc
::SOL_SOCKET
;
196 cmsg
.hdr
.cmsg_type
= 1; // SCM_RIGHTS
198 let mut msg
: libc
::msghdr
= mem
::zeroed();
199 msg
.msg_iov
= &mut iov
;
201 msg
.msg_control
= &mut cmsg
as *mut _
as *mut _
;
202 msg
.msg_controllen
= mem
::size_of_val(&cmsg
).my_into();
203 let bytes
= cvt(libc
::sendmsg(self.as_raw_fd(), &msg
, 0))?
;
209 impl Read
for UnixSocket
{
210 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
215 impl Write
for UnixSocket
{
216 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
220 fn flush(&mut self) -> io
::Result
<()> {
225 impl Evented
for UnixSocket
{
226 fn register(&self, poll
: &Poll
, token
: Token
, interest
: Ready
, opts
: PollOpt
) -> io
::Result
<()> {
227 self.io
.register(poll
, token
, interest
, opts
)
230 fn reregister(&self, poll
: &Poll
, token
: Token
, interest
: Ready
, opts
: PollOpt
) -> io
::Result
<()> {
231 self.io
.reregister(poll
, token
, interest
, opts
)
234 fn deregister(&self, poll
: &Poll
) -> io
::Result
<()> {
235 self.io
.deregister(poll
)
240 impl From
<Io
> for UnixSocket
{
241 fn from(io
: Io
) -> UnixSocket
{
246 impl FromRawFd
for UnixSocket
{
247 unsafe fn from_raw_fd(fd
: RawFd
) -> UnixSocket
{
248 UnixSocket { io: Io::from_raw_fd(fd) }
252 impl IntoRawFd
for UnixSocket
{
253 fn into_raw_fd(self) -> RawFd
{
254 self.io
.into_raw_fd()
258 impl AsRawFd
for UnixSocket
{
259 fn as_raw_fd(&self) -> RawFd
{