1 //! Primitives for working with UDP
2 //!
3 //! The types provided in this module are non-blocking by default and are
4 //! designed to be portable across all supported Mio platforms. As long as the
5 //! [portability guidelines] are followed, the behavior should be identical no
6 //! matter the target platform.
7 //!
8 //! [portability guidelines]: ../struct.Poll.html#portability
9 
10 #![allow(deprecated)]
11 
12 use {sys, Ready, Poll, PollOpt, Token};
13 use io::{self, MapNonBlock};
14 use event::Evented;
15 use poll::SelectorId;
16 use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
17 
18 /// A User Datagram Protocol socket.
19 ///
20 /// This is an implementation of a bound UDP socket. This supports both IPv4 and
21 /// IPv6 addresses, and there is no corresponding notion of a server because UDP
22 /// is a datagram protocol.
23 #[derive(Debug)]
24 pub struct UdpSocket {
25     sys: sys::UdpSocket,
26     selector_id: SelectorId,
27 }
28 
29 impl UdpSocket {
30     /// Creates a UDP socket from the given address.
bind(addr: &SocketAddr) -> io::Result<UdpSocket>31     pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> {
32         let socket = net::UdpSocket::bind(addr)?;
33         UdpSocket::from_socket(socket)
34     }
35 
36     /// Creates a new mio-wrapped socket from an underlying and bound std
37     /// socket.
38     ///
39     /// This function requires that `socket` has previously been bound to an
40     /// address to work correctly, and returns an I/O object which can be used
41     /// with mio to send/receive UDP messages.
42     ///
43     /// This can be used in conjunction with net2's `UdpBuilder` interface to
44     /// configure a socket before it's handed off to mio, such as setting
45     /// options like `reuse_address` or binding to multiple addresses.
from_socket(socket: net::UdpSocket) -> io::Result<UdpSocket>46     pub fn from_socket(socket: net::UdpSocket) -> io::Result<UdpSocket> {
47         Ok(UdpSocket {
48             sys: sys::UdpSocket::new(socket)?,
49             selector_id: SelectorId::new(),
50         })
51     }
52 
53     /// Returns the socket address that this socket was created from.
local_addr(&self) -> io::Result<SocketAddr>54     pub fn local_addr(&self) -> io::Result<SocketAddr> {
55         self.sys.local_addr()
56     }
57 
58     /// Creates a new independently owned handle to the underlying socket.
59     ///
60     /// The returned `UdpSocket` is a reference to the same socket that this
61     /// object references. Both handles will read and write the same port, and
62     /// options set on one socket will be propagated to the other.
try_clone(&self) -> io::Result<UdpSocket>63     pub fn try_clone(&self) -> io::Result<UdpSocket> {
64         self.sys.try_clone()
65             .map(|s| {
66                 UdpSocket {
67                     sys: s,
68                     selector_id: self.selector_id.clone(),
69                 }
70             })
71     }
72 
73     /// Sends data on the socket to the given address. On success, returns the
74     /// number of bytes written.
75     ///
76     /// Address type can be any implementor of `ToSocketAddrs` trait. See its
77     /// documentation for concrete examples.
send_to(&self, buf: &[u8], target: &SocketAddr) -> io::Result<Option<usize>>78     pub fn send_to(&self, buf: &[u8], target: &SocketAddr)
79                    -> io::Result<Option<usize>> {
80         self.sys.send_to(buf, target).map_non_block()
81     }
82 
83     /// Receives data from the socket and stores data in the supplied buffer `buf`. On success,
84     /// returns the number of bytes read and the address from whence the data came.
85     ///
86     /// The function must be called with valid byte array `buf` of sufficient size to
87     /// hold the message bytes. If a message is too long to fit in the supplied buffer,
88     /// excess bytes may be discarded.
89     ///
90     /// The function does not read from `buf`, but is overwriting previous content of `buf`.
91     ///
92     /// Assuming the function has read `n` bytes, slicing `&buf[..n]` provides
93     /// efficient access with iterators and boundary checks.
recv_from(&self, buf: &mut [u8]) -> io::Result<Option<(usize, SocketAddr)>>94     pub fn recv_from(&self, buf: &mut [u8])
95                      -> io::Result<Option<(usize, SocketAddr)>> {
96         self.sys.recv_from(buf).map_non_block()
97     }
98 
99     /// Sends data on the socket to the address previously bound via connect(). On success,
100     /// returns the number of bytes written.
send(&self, buf: &[u8]) -> io::Result<Option<usize>>101     pub fn send(&self, buf: &[u8])
102                    -> io::Result<Option<usize>> {
103         self.sys.send(buf).map_non_block()
104     }
105 
106     /// Receives data from the socket previously bound with connect() and stores data in
107     /// the supplied buffer `buf`. On success, returns the number of bytes read.
108     ///
109     /// The function must be called with valid byte array `buf` of sufficient size to
110     /// hold the message bytes. If a message is too long to fit in the supplied buffer,
111     /// excess bytes may be discarded.
112     ///
113     /// The function does not read from `buf`, but is overwriting previous content of `buf`.
114     ///
115     /// Assuming the function has read `n` bytes, slicing `&buf[..n]` provides
116     /// efficient access with iterators and boundary checks.
recv(&self, buf: &mut [u8]) -> io::Result<Option<usize>>117     pub fn recv(&self, buf: &mut [u8])
118                      -> io::Result<Option<usize>> {
119         self.sys.recv(buf).map_non_block()
120     }
121 
122     /// Connects the UDP socket setting the default destination for `send()`
123     /// and limiting packets that are read via `recv` from the address specified
124     /// in `addr`.
connect(&self, addr: SocketAddr) -> io::Result<()>125     pub fn connect(&self, addr: SocketAddr)
126                  -> io::Result<()> {
127         self.sys.connect(addr)
128     }
129 
130     /// Gets the value of the `SO_BROADCAST` option for this socket.
131     ///
132     /// For more information about this option, see
133     /// [`set_broadcast`][link].
134     ///
135     /// [link]: #method.set_broadcast
broadcast(&self) -> io::Result<bool>136     pub fn broadcast(&self) -> io::Result<bool> {
137         self.sys.broadcast()
138     }
139 
140     /// Sets the value of the `SO_BROADCAST` option for this socket.
141     ///
142     /// When enabled, this socket is allowed to send packets to a broadcast
143     /// address.
set_broadcast(&self, on: bool) -> io::Result<()>144     pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
145         self.sys.set_broadcast(on)
146     }
147 
148     /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
149     ///
150     /// For more information about this option, see
151     /// [`set_multicast_loop_v4`][link].
152     ///
153     /// [link]: #method.set_multicast_loop_v4
multicast_loop_v4(&self) -> io::Result<bool>154     pub fn multicast_loop_v4(&self) -> io::Result<bool> {
155         self.sys.multicast_loop_v4()
156     }
157 
158     /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
159     ///
160     /// If enabled, multicast packets will be looped back to the local socket.
161     /// Note that this may not have any affect on IPv6 sockets.
set_multicast_loop_v4(&self, on: bool) -> io::Result<()>162     pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
163         self.sys.set_multicast_loop_v4(on)
164     }
165 
166     /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
167     ///
168     /// For more information about this option, see
169     /// [`set_multicast_ttl_v4`][link].
170     ///
171     /// [link]: #method.set_multicast_ttl_v4
multicast_ttl_v4(&self) -> io::Result<u32>172     pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
173         self.sys.multicast_ttl_v4()
174     }
175 
176     /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
177     ///
178     /// Indicates the time-to-live value of outgoing multicast packets for
179     /// this socket. The default value is 1 which means that multicast packets
180     /// don't leave the local network unless explicitly requested.
181     ///
182     /// Note that this may not have any affect on IPv6 sockets.
set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()>183     pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
184         self.sys.set_multicast_ttl_v4(ttl)
185     }
186 
187     /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
188     ///
189     /// For more information about this option, see
190     /// [`set_multicast_loop_v6`][link].
191     ///
192     /// [link]: #method.set_multicast_loop_v6
multicast_loop_v6(&self) -> io::Result<bool>193     pub fn multicast_loop_v6(&self) -> io::Result<bool> {
194         self.sys.multicast_loop_v6()
195     }
196 
197     /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
198     ///
199     /// Controls whether this socket sees the multicast packets it sends itself.
200     /// Note that this may not have any affect on IPv4 sockets.
set_multicast_loop_v6(&self, on: bool) -> io::Result<()>201     pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
202         self.sys.set_multicast_loop_v6(on)
203     }
204 
205     /// Gets the value of the `IP_TTL` option for this socket.
206     ///
207     /// For more information about this option, see [`set_ttl`][link].
208     ///
209     /// [link]: #method.set_ttl
ttl(&self) -> io::Result<u32>210     pub fn ttl(&self) -> io::Result<u32> {
211         self.sys.ttl()
212     }
213 
214     /// Sets the value for the `IP_TTL` option on this socket.
215     ///
216     /// This value sets the time-to-live field that is used in every packet sent
217     /// from this socket.
set_ttl(&self, ttl: u32) -> io::Result<()>218     pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
219         self.sys.set_ttl(ttl)
220     }
221 
222     /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
223     ///
224     /// This function specifies a new multicast group for this socket to join.
225     /// The address must be a valid multicast address, and `interface` is the
226     /// address of the local interface with which the system should join the
227     /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
228     /// interface is chosen by the system.
join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>229     pub fn join_multicast_v4(&self,
230                              multiaddr: &Ipv4Addr,
231                              interface: &Ipv4Addr) -> io::Result<()> {
232         self.sys.join_multicast_v4(multiaddr, interface)
233     }
234 
235     /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
236     ///
237     /// This function specifies a new multicast group for this socket to join.
238     /// The address must be a valid multicast address, and `interface` is the
239     /// index of the interface to join/leave (or 0 to indicate any interface).
join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>240     pub fn join_multicast_v6(&self,
241                              multiaddr: &Ipv6Addr,
242                              interface: u32) -> io::Result<()> {
243         self.sys.join_multicast_v6(multiaddr, interface)
244     }
245 
246     /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
247     ///
248     /// For more information about this option, see
249     /// [`join_multicast_v4`][link].
250     ///
251     /// [link]: #method.join_multicast_v4
leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()>252     pub fn leave_multicast_v4(&self,
253                               multiaddr: &Ipv4Addr,
254                               interface: &Ipv4Addr) -> io::Result<()> {
255         self.sys.leave_multicast_v4(multiaddr, interface)
256     }
257 
258     /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
259     ///
260     /// For more information about this option, see
261     /// [`join_multicast_v6`][link].
262     ///
263     /// [link]: #method.join_multicast_v6
leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()>264     pub fn leave_multicast_v6(&self,
265                               multiaddr: &Ipv6Addr,
266                               interface: u32) -> io::Result<()> {
267         self.sys.leave_multicast_v6(multiaddr, interface)
268     }
269 
270     /// Get the value of the `SO_ERROR` option on this socket.
271     ///
272     /// This will retrieve the stored error in the underlying socket, clearing
273     /// the field in the process. This can be useful for checking errors between
274     /// calls.
take_error(&self) -> io::Result<Option<io::Error>>275     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
276         self.sys.take_error()
277     }
278 }
279 
280 impl Evented for UdpSocket {
register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()>281     fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
282         self.selector_id.associate_selector(poll)?;
283         self.sys.register(poll, token, interest, opts)
284     }
285 
reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()>286     fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
287         self.sys.reregister(poll, token, interest, opts)
288     }
289 
deregister(&self, poll: &Poll) -> io::Result<()>290     fn deregister(&self, poll: &Poll) -> io::Result<()> {
291         self.sys.deregister(poll)
292     }
293 }
294 
295 /*
296  *
297  * ===== UNIX ext =====
298  *
299  */
300 
301 #[cfg(all(unix, not(target_os = "fuchsia")))]
302 use std::os::unix::io::{IntoRawFd, AsRawFd, FromRawFd, RawFd};
303 
304 #[cfg(all(unix, not(target_os = "fuchsia")))]
305 impl IntoRawFd for UdpSocket {
into_raw_fd(self) -> RawFd306     fn into_raw_fd(self) -> RawFd {
307         self.sys.into_raw_fd()
308     }
309 }
310 
311 #[cfg(all(unix, not(target_os = "fuchsia")))]
312 impl AsRawFd for UdpSocket {
as_raw_fd(&self) -> RawFd313     fn as_raw_fd(&self) -> RawFd {
314         self.sys.as_raw_fd()
315     }
316 }
317 
318 #[cfg(all(unix, not(target_os = "fuchsia")))]
319 impl FromRawFd for UdpSocket {
from_raw_fd(fd: RawFd) -> UdpSocket320     unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
321         UdpSocket {
322             sys: FromRawFd::from_raw_fd(fd),
323             selector_id: SelectorId::new(),
324         }
325     }
326 }
327