mio_uds/
datagram.rs

1use std::io;
2use std::net::Shutdown;
3use std::os::unix::net;
4use std::os::unix::prelude::*;
5use std::path::Path;
6
7use libc;
8use mio::event::Evented;
9use mio::unix::EventedFd;
10use mio::{Poll, Token, Ready, PollOpt};
11
12use cvt;
13use socket::{sockaddr_un, Socket};
14
15/// A Unix datagram socket.
16#[derive(Debug)]
17pub struct UnixDatagram {
18    inner: net::UnixDatagram,
19}
20
21impl UnixDatagram {
22    /// Creates a Unix datagram socket bound to the given path.
23    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
24        UnixDatagram::_bind(path.as_ref())
25    }
26
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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`).
140    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
141        self.inner.shutdown(how)
142    }
143}
144
145impl Evented for UnixDatagram {
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
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
162    fn deregister(&self, poll: &Poll) -> io::Result<()> {
163        EventedFd(&self.as_raw_fd()).deregister(poll)
164    }
165}
166
167impl AsRawFd for UnixDatagram {
168    fn as_raw_fd(&self) -> i32 {
169        self.inner.as_raw_fd()
170    }
171}
172
173impl IntoRawFd for UnixDatagram {
174    fn into_raw_fd(self) -> i32 {
175        self.inner.into_raw_fd()
176    }
177}
178
179impl FromRawFd for UnixDatagram {
180    unsafe fn from_raw_fd(fd: i32) -> UnixDatagram {
181        UnixDatagram { inner: net::UnixDatagram::from_raw_fd(fd) }
182    }
183}