1 use std::io;
2 use std::net::Shutdown;
3 use std::os::unix::net;
4 use std::os::unix::prelude::*;
5 use std::path::Path;
6 
7 use libc;
8 use mio::event::Evented;
9 use mio::unix::EventedFd;
10 use mio::{Poll, Token, Ready, PollOpt};
11 
12 use cvt;
13 use socket::{sockaddr_un, Socket};
14 
15 /// A Unix datagram socket.
16 #[derive(Debug)]
17 pub struct UnixDatagram {
18     inner: net::UnixDatagram,
19 }
20 
21 impl UnixDatagram {
22     /// Creates a Unix datagram socket bound to the given path.
bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram>23     pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
24         UnixDatagram::_bind(path.as_ref())
25     }
26 
_bind(path: &Path) -> io::Result<UnixDatagram>27     fn _bind(path: &Path) -> io::Result<UnixDatagram> {
28         unsafe {
29             let (addr, len) = try!(sockaddr_un(path));
30             let fd = try!(Socket::new(libc::SOCK_DGRAM));
31 
32             let addr = &addr as *const _ as *const _;
33             try!(cvt(libc::bind(fd.fd(), addr, len)));
34 
35             Ok(UnixDatagram::from_raw_fd(fd.into_fd()))
36         }
37     }
38 
39     /// Consumes a standard library `UnixDatagram` and returns a wrapped
40     /// `UnixDatagram` compatible with mio.
41     ///
42     /// The returned stream is moved into nonblocking mode and is otherwise
43     /// ready to get associated with an event loop.
from_datagram(stream: net::UnixDatagram) -> io::Result<UnixDatagram>44     pub fn from_datagram(stream: net::UnixDatagram) -> io::Result<UnixDatagram> {
45         try!(stream.set_nonblocking(true));
46         Ok(UnixDatagram { inner: stream })
47     }
48 
49     /// Create an unnamed pair of connected sockets.
50     ///
51     /// Returns two `UnixDatagrams`s which are connected to each other.
pair() -> io::Result<(UnixDatagram, UnixDatagram)>52     pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
53         unsafe {
54             let (a, b) = try!(Socket::pair(libc::SOCK_DGRAM));
55             Ok((UnixDatagram::from_raw_fd(a.into_fd()),
56                 UnixDatagram::from_raw_fd(b.into_fd())))
57         }
58     }
59 
60     /// Creates a Unix Datagram socket which is not bound to any address.
unbound() -> io::Result<UnixDatagram>61     pub fn unbound() -> io::Result<UnixDatagram> {
62         let stream = try!(net::UnixDatagram::unbound());
63         try!(stream.set_nonblocking(true));
64         Ok(UnixDatagram { inner: stream })
65     }
66 
67     /// Connects the socket to the specified address.
68     ///
69     /// The `send` method may be used to send data to the specified address.
70     /// `recv` and `recv_from` will only receive data from that address.
connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()>71     pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
72         self.inner.connect(path)
73     }
74 
75     /// Creates a new independently owned handle to the underlying socket.
76     ///
77     /// The returned `UnixListener` is a reference to the same socket that this
78     /// object references. Both handles can be used to accept incoming
79     /// connections and options set on one listener will affect the other.
try_clone(&self) -> io::Result<UnixDatagram>80     pub fn try_clone(&self) -> io::Result<UnixDatagram> {
81         self.inner.try_clone().map(|i| {
82             UnixDatagram { inner: i }
83         })
84     }
85 
86     /// Returns the address of this socket.
local_addr(&self) -> io::Result<net::SocketAddr>87     pub fn local_addr(&self) -> io::Result<net::SocketAddr> {
88         self.inner.local_addr()
89     }
90 
91     /// Returns the address of this socket's peer.
92     ///
93     /// The `connect` method will connect the socket to a peer.
peer_addr(&self) -> io::Result<net::SocketAddr>94     pub fn peer_addr(&self) -> io::Result<net::SocketAddr> {
95         self.inner.peer_addr()
96     }
97 
98     /// Receives data from the socket.
99     ///
100     /// On success, returns the number of bytes read and the address from
101     /// whence the data came.
recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, net::SocketAddr)>102     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, net::SocketAddr)> {
103         self.inner.recv_from(buf)
104     }
105 
106     /// Receives data from the socket.
107     ///
108     /// On success, returns the number of bytes read.
recv(&self, buf: &mut [u8]) -> io::Result<usize>109     pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
110         self.inner.recv(buf)
111     }
112 
113     /// Sends data on the socket to the specified address.
114     ///
115     /// On success, returns the number of bytes written.
send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize>116     pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
117         self.inner.send_to(buf, path)
118     }
119 
120     /// Sends data on the socket to the socket's peer.
121     ///
122     /// The peer address may be set by the `connect` method, and this method
123     /// will return an error if the socket has not already been connected.
124     ///
125     /// On success, returns the number of bytes written.
send(&self, buf: &[u8]) -> io::Result<usize>126     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
127         self.inner.send(buf)
128     }
129 
130     /// Returns the value of the `SO_ERROR` option.
take_error(&self) -> io::Result<Option<io::Error>>131     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
132         self.inner.take_error()
133     }
134 
135     /// Shut down the read, write, or both halves of this connection.
136     ///
137     /// This function will cause all pending and future I/O calls on the
138     /// specified portions to immediately return with an appropriate value
139     /// (see the documentation of `Shutdown`).
shutdown(&self, how: Shutdown) -> io::Result<()>140     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
141         self.inner.shutdown(how)
142     }
143 }
144 
145 impl Evented for UnixDatagram {
register(&self, poll: &Poll, token: Token, events: Ready, opts: PollOpt) -> io::Result<()>146     fn register(&self,
147                 poll: &Poll,
148                 token: Token,
149                 events: Ready,
150                 opts: PollOpt) -> io::Result<()> {
151         EventedFd(&self.as_raw_fd()).register(poll, token, events, opts)
152     }
153 
reregister(&self, poll: &Poll, token: Token, events: Ready, opts: PollOpt) -> io::Result<()>154     fn reregister(&self,
155                   poll: &Poll,
156                   token: Token,
157                   events: Ready,
158                   opts: PollOpt) -> io::Result<()> {
159         EventedFd(&self.as_raw_fd()).reregister(poll, token, events, opts)
160     }
161 
deregister(&self, poll: &Poll) -> io::Result<()>162     fn deregister(&self, poll: &Poll) -> io::Result<()> {
163         EventedFd(&self.as_raw_fd()).deregister(poll)
164     }
165 }
166 
167 impl AsRawFd for UnixDatagram {
as_raw_fd(&self) -> i32168     fn as_raw_fd(&self) -> i32 {
169         self.inner.as_raw_fd()
170     }
171 }
172 
173 impl IntoRawFd for UnixDatagram {
into_raw_fd(self) -> i32174     fn into_raw_fd(self) -> i32 {
175         self.inner.into_raw_fd()
176     }
177 }
178 
179 impl FromRawFd for UnixDatagram {
from_raw_fd(fd: i32) -> UnixDatagram180     unsafe fn from_raw_fd(fd: i32) -> UnixDatagram {
181         UnixDatagram { inner: net::UnixDatagram::from_raw_fd(fd) }
182     }
183 }
184