tokio_udp/socket.rs
1use super::{RecvDgram, SendDgram};
2
3use std::fmt;
4use std::io;
5use std::net::{self, Ipv4Addr, Ipv6Addr, SocketAddr};
6
7use futures::{Async, Poll};
8use mio;
9
10use tokio_reactor::{Handle, PollEvented};
11
12/// An I/O object representing a UDP socket.
13pub struct UdpSocket {
14 io: PollEvented<mio::net::UdpSocket>,
15}
16
17impl UdpSocket {
18 /// This function will create a new UDP socket and attempt to bind it to
19 /// the `addr` provided.
20 pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> {
21 mio::net::UdpSocket::bind(addr).map(UdpSocket::new)
22 }
23
24 fn new(socket: mio::net::UdpSocket) -> UdpSocket {
25 let io = PollEvented::new(socket);
26 UdpSocket { io: io }
27 }
28
29 /// Creates a new `UdpSocket` from the previously bound socket provided.
30 ///
31 /// The socket given will be registered with the event loop that `handle`
32 /// is associated with. This function requires that `socket` has previously
33 /// been bound to an address to work correctly.
34 ///
35 /// This can be used in conjunction with net2's `UdpBuilder` interface to
36 /// configure a socket before it's handed off, such as setting options like
37 /// `reuse_address` or binding to multiple addresses.
38 ///
39 /// Use `Handle::default()` to lazily bind to an event loop, just like `bind` does.
40 pub fn from_std(socket: net::UdpSocket, handle: &Handle) -> io::Result<UdpSocket> {
41 let io = mio::net::UdpSocket::from_socket(socket)?;
42 let io = PollEvented::new_with_handle(io, handle)?;
43 Ok(UdpSocket { io })
44 }
45
46 /// Returns the local address that this socket is bound to.
47 pub fn local_addr(&self) -> io::Result<SocketAddr> {
48 self.io.get_ref().local_addr()
49 }
50
51 /// Connects the UDP socket setting the default destination for send() and
52 /// limiting packets that are read via recv from the address specified in
53 /// `addr`.
54 pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
55 self.io.get_ref().connect(*addr)
56 }
57
58 #[deprecated(since = "0.1.2", note = "use poll_send instead")]
59 #[doc(hidden)]
60 pub fn send(&mut self, buf: &[u8]) -> io::Result<usize> {
61 match self.poll_send(buf)? {
62 Async::Ready(n) => Ok(n),
63 Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
64 }
65 }
66
67 /// Sends data on the socket to the remote address to which it is connected.
68 ///
69 /// The [`connect`] method will connect this socket to a remote address. This
70 /// method will fail if the socket is not connected.
71 ///
72 /// [`connect`]: #method.connect
73 ///
74 /// # Return
75 ///
76 /// On success, returns `Ok(Async::Ready(num_bytes_written))`.
77 ///
78 /// If the socket is not ready for writing, the method returns
79 /// `Ok(Async::NotReady)` and arranges for the current task to receive a
80 /// notification when the socket becomes writable.
81 ///
82 /// # Panics
83 ///
84 /// This function will panic if called from outside of a task context.
85 pub fn poll_send(&mut self, buf: &[u8]) -> Poll<usize, io::Error> {
86 try_ready!(self.io.poll_write_ready());
87
88 match self.io.get_ref().send(buf) {
89 Ok(n) => Ok(n.into()),
90 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
91 self.io.clear_write_ready()?;
92 Ok(Async::NotReady)
93 }
94 Err(e) => Err(e),
95 }
96 }
97
98 #[deprecated(since = "0.1.2", note = "use poll_recv instead")]
99 #[doc(hidden)]
100 pub fn recv(&mut self, buf: &mut [u8]) -> io::Result<usize> {
101 match self.poll_recv(buf)? {
102 Async::Ready(n) => Ok(n),
103 Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
104 }
105 }
106
107 /// Receives a single datagram message on the socket from the remote address to
108 /// which it is connected. On success, returns the number of bytes read.
109 ///
110 /// The function must be called with valid byte array `buf` of sufficient size to
111 /// hold the message bytes. If a message is too long to fit in the supplied buffer,
112 /// excess bytes may be discarded.
113 ///
114 /// The [`connect`] method will connect this socket to a remote address. This
115 /// method will fail if the socket is not connected.
116 ///
117 /// [`connect`]: #method.connect
118 ///
119 /// # Return
120 ///
121 /// On success, returns `Ok(Async::Ready(num_bytes_read))`.
122 ///
123 /// If no data is available for reading, the method returns
124 /// `Ok(Async::NotReady)` and arranges for the current task to receive a
125 /// notification when the socket becomes receivable or is closed.
126 ///
127 /// # Panics
128 ///
129 /// This function will panic if called from outside of a task context.
130 pub fn poll_recv(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
131 try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
132
133 match self.io.get_ref().recv(buf) {
134 Ok(n) => Ok(n.into()),
135 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
136 self.io.clear_read_ready(mio::Ready::readable())?;
137 Ok(Async::NotReady)
138 }
139 Err(e) => Err(e),
140 }
141 }
142
143 #[deprecated(since = "0.1.2", note = "use poll_send_to instead")]
144 #[doc(hidden)]
145 pub fn send_to(&mut self, buf: &[u8], target: &SocketAddr) -> io::Result<usize> {
146 match self.poll_send_to(buf, target)? {
147 Async::Ready(n) => Ok(n),
148 Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
149 }
150 }
151
152 /// Sends data on the socket to the given address. On success, returns the
153 /// number of bytes written.
154 ///
155 /// This will return an error when the IP version of the local socket
156 /// does not match that of `target`.
157 ///
158 /// # Return
159 ///
160 /// On success, returns `Ok(Async::Ready(num_bytes_written))`.
161 ///
162 /// If the socket is not ready for writing, the method returns
163 /// `Ok(Async::NotReady)` and arranges for the current task to receive a
164 /// notification when the socket becomes writable.
165 ///
166 /// # Panics
167 ///
168 /// This function will panic if called from outside of a task context.
169 pub fn poll_send_to(&mut self, buf: &[u8], target: &SocketAddr) -> Poll<usize, io::Error> {
170 try_ready!(self.io.poll_write_ready());
171
172 match self.io.get_ref().send_to(buf, target) {
173 Ok(n) => Ok(n.into()),
174 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
175 self.io.clear_write_ready()?;
176 Ok(Async::NotReady)
177 }
178 Err(e) => Err(e),
179 }
180 }
181
182 /// Creates a future that will write the entire contents of the buffer
183 /// `buf` provided as a datagram to this socket.
184 ///
185 /// The returned future will return after data has been written to the
186 /// outbound socket. The future will resolve to the stream as well as the
187 /// buffer (for reuse if needed).
188 ///
189 /// Any error which happens during writing will cause both the stream and
190 /// the buffer to get destroyed. Note that failure to write the entire
191 /// buffer is considered an error for the purposes of sending a datagram.
192 ///
193 /// The `buf` parameter here only requires the `AsRef<[u8]>` trait, which
194 /// should be broadly applicable to accepting data which can be converted
195 /// to a slice.
196 pub fn send_dgram<T>(self, buf: T, addr: &SocketAddr) -> SendDgram<T>
197 where
198 T: AsRef<[u8]>,
199 {
200 SendDgram::new(self, buf, *addr)
201 }
202
203 #[deprecated(since = "0.1.2", note = "use poll_recv_from instead")]
204 #[doc(hidden)]
205 pub fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
206 match self.poll_recv_from(buf)? {
207 Async::Ready(ret) => Ok(ret),
208 Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
209 }
210 }
211
212 /// Receives data from the socket. On success, returns the number of bytes
213 /// read and the address from whence the data came.
214 ///
215 /// # Panics
216 ///
217 /// This function will panic if called outside the context of a future's
218 /// task.
219 pub fn poll_recv_from(&mut self, buf: &mut [u8]) -> Poll<(usize, SocketAddr), io::Error> {
220 try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
221
222 match self.io.get_ref().recv_from(buf) {
223 Ok(n) => Ok(n.into()),
224 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
225 self.io.clear_read_ready(mio::Ready::readable())?;
226 Ok(Async::NotReady)
227 }
228 Err(e) => Err(e),
229 }
230 }
231
232 /// Creates a future that receive a datagram to be written to the buffer
233 /// provided.
234 ///
235 /// The returned future will return after a datagram has been received on
236 /// this socket. The future will resolve to the socket, the buffer, the
237 /// amount of data read, and the address the data was received from.
238 ///
239 /// An error during reading will cause the socket and buffer to get
240 /// destroyed.
241 ///
242 /// The `buf` parameter here only requires the `AsMut<[u8]>` trait, which
243 /// should be broadly applicable to accepting data which can be converted
244 /// to a slice.
245 pub fn recv_dgram<T>(self, buf: T) -> RecvDgram<T>
246 where
247 T: AsMut<[u8]>,
248 {
249 RecvDgram::new(self, buf)
250 }
251
252 /// Check the UDP socket's read readiness state.
253 ///
254 /// The mask argument allows specifying what readiness to notify on. This
255 /// can be any value, including platform specific readiness, **except**
256 /// `writable`.
257 ///
258 /// If the socket is not ready for receiving then `Async::NotReady` is
259 /// returned and the current task is notified once a new event is received.
260 ///
261 /// The socket will remain in a read-ready state until calls to `poll_recv`
262 /// return `NotReady`.
263 ///
264 /// # Panics
265 ///
266 /// This function panics if:
267 ///
268 /// * `ready` includes writable.
269 /// * called from outside of a task context.
270 pub fn poll_read_ready(&self, mask: mio::Ready) -> Poll<mio::Ready, io::Error> {
271 self.io.poll_read_ready(mask)
272 }
273
274 /// Check the UDP socket's write readiness state.
275 ///
276 /// If the socket is not ready for sending then `Async::NotReady` is
277 /// returned and the current task is notified once a new event is received.
278 ///
279 /// The I/O resource will remain in a write-ready state until calls to
280 /// `poll_send` return `NotReady`.
281 ///
282 /// # Panics
283 ///
284 /// This function panics if called from outside of a task context.
285 pub fn poll_write_ready(&self) -> Poll<mio::Ready, io::Error> {
286 self.io.poll_write_ready()
287 }
288
289 /// Gets the value of the `SO_BROADCAST` option for this socket.
290 ///
291 /// For more information about this option, see [`set_broadcast`].
292 ///
293 /// [`set_broadcast`]: #method.set_broadcast
294 pub fn broadcast(&self) -> io::Result<bool> {
295 self.io.get_ref().broadcast()
296 }
297
298 /// Sets the value of the `SO_BROADCAST` option for this socket.
299 ///
300 /// When enabled, this socket is allowed to send packets to a broadcast
301 /// address.
302 pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
303 self.io.get_ref().set_broadcast(on)
304 }
305
306 /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
307 ///
308 /// For more information about this option, see [`set_multicast_loop_v4`].
309 ///
310 /// [`set_multicast_loop_v4`]: #method.set_multicast_loop_v4
311 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
312 self.io.get_ref().multicast_loop_v4()
313 }
314
315 /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
316 ///
317 /// If enabled, multicast packets will be looped back to the local socket.
318 ///
319 /// # Note
320 ///
321 /// This may not have any affect on IPv6 sockets.
322 pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
323 self.io.get_ref().set_multicast_loop_v4(on)
324 }
325
326 /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
327 ///
328 /// For more information about this option, see [`set_multicast_ttl_v4`].
329 ///
330 /// [`set_multicast_ttl_v4`]: #method.set_multicast_ttl_v4
331 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
332 self.io.get_ref().multicast_ttl_v4()
333 }
334
335 /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
336 ///
337 /// Indicates the time-to-live value of outgoing multicast packets for
338 /// this socket. The default value is 1 which means that multicast packets
339 /// don't leave the local network unless explicitly requested.
340 ///
341 /// # Note
342 ///
343 /// This may not have any affect on IPv6 sockets.
344 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
345 self.io.get_ref().set_multicast_ttl_v4(ttl)
346 }
347
348 /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
349 ///
350 /// For more information about this option, see [`set_multicast_loop_v6`].
351 ///
352 /// [`set_multicast_loop_v6`]: #method.set_multicast_loop_v6
353 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
354 self.io.get_ref().multicast_loop_v6()
355 }
356
357 /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
358 ///
359 /// Controls whether this socket sees the multicast packets it sends itself.
360 ///
361 /// # Note
362 ///
363 /// This may not have any affect on IPv4 sockets.
364 pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
365 self.io.get_ref().set_multicast_loop_v6(on)
366 }
367
368 /// Gets the value of the `IP_TTL` option for this socket.
369 ///
370 /// For more information about this option, see [`set_ttl`].
371 ///
372 /// [`set_ttl`]: #method.set_ttl
373 pub fn ttl(&self) -> io::Result<u32> {
374 self.io.get_ref().ttl()
375 }
376
377 /// Sets the value for the `IP_TTL` option on this socket.
378 ///
379 /// This value sets the time-to-live field that is used in every packet sent
380 /// from this socket.
381 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
382 self.io.get_ref().set_ttl(ttl)
383 }
384
385 /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
386 ///
387 /// This function specifies a new multicast group for this socket to join.
388 /// The address must be a valid multicast address, and `interface` is the
389 /// address of the local interface with which the system should join the
390 /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
391 /// interface is chosen by the system.
392 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
393 self.io.get_ref().join_multicast_v4(multiaddr, interface)
394 }
395
396 /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
397 ///
398 /// This function specifies a new multicast group for this socket to join.
399 /// The address must be a valid multicast address, and `interface` is the
400 /// index of the interface to join/leave (or 0 to indicate any interface).
401 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
402 self.io.get_ref().join_multicast_v6(multiaddr, interface)
403 }
404
405 /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
406 ///
407 /// For more information about this option, see [`join_multicast_v4`].
408 ///
409 /// [`join_multicast_v4`]: #method.join_multicast_v4
410 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
411 self.io.get_ref().leave_multicast_v4(multiaddr, interface)
412 }
413
414 /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
415 ///
416 /// For more information about this option, see [`join_multicast_v6`].
417 ///
418 /// [`join_multicast_v6`]: #method.join_multicast_v6
419 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
420 self.io.get_ref().leave_multicast_v6(multiaddr, interface)
421 }
422}
423
424impl fmt::Debug for UdpSocket {
425 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
426 self.io.get_ref().fmt(f)
427 }
428}
429
430#[cfg(all(unix))]
431mod sys {
432 use super::UdpSocket;
433 use std::os::unix::prelude::*;
434
435 impl AsRawFd for UdpSocket {
436 fn as_raw_fd(&self) -> RawFd {
437 self.io.get_ref().as_raw_fd()
438 }
439 }
440}
441
442#[cfg(windows)]
443mod sys {
444 // TODO: let's land these upstream with mio and then we can add them here.
445 //
446 // use std::os::windows::prelude::*;
447 // use super::UdpSocket;
448 //
449 // impl AsRawHandle for UdpSocket {
450 // fn as_raw_handle(&self) -> RawHandle {
451 // self.io.get_ref().as_raw_handle()
452 // }
453 // }
454}