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