]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/net/udp.rs
Merge pull request #20510 from tshepang/patch-6
[rust.git] / src / libstd / io / net / udp.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! UDP (User Datagram Protocol) network connections.
12 //!
13 //! This module contains the ability to open a UDP stream to a socket address.
14 //! The destination and binding addresses can either be an IPv4 or IPv6
15 //! address. There is no corresponding notion of a server because UDP is a
16 //! datagram protocol.
17
18 use clone::Clone;
19 use io::net::ip::{SocketAddr, IpAddr, ToSocketAddr};
20 use io::IoResult;
21 use option::Option;
22 use sys::udp::UdpSocket as UdpSocketImp;
23 use sys_common;
24
25 /// A User Datagram Protocol socket.
26 ///
27 /// This is an implementation of a bound UDP socket. This supports both IPv4 and
28 /// IPv6 addresses, and there is no corresponding notion of a server because UDP
29 /// is a datagram protocol.
30 ///
31 /// # Example
32 ///
33 /// ```rust,no_run
34 /// # #![allow(unused_must_use)]
35 /// #![feature(slicing_syntax)]
36 ///
37 /// use std::io::net::udp::UdpSocket;
38 /// use std::io::net::ip::{Ipv4Addr, SocketAddr};
39 /// fn main() {
40 ///     let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 34254 };
41 ///     let mut socket = match UdpSocket::bind(addr) {
42 ///         Ok(s) => s,
43 ///         Err(e) => panic!("couldn't bind socket: {}", e),
44 ///     };
45 ///
46 ///     let mut buf = [0; 10];
47 ///     match socket.recv_from(&mut buf) {
48 ///         Ok((amt, src)) => {
49 ///             // Send a reply to the socket we received data from
50 ///             let buf = buf.slice_to_mut(amt);
51 ///             buf.reverse();
52 ///             socket.send_to(buf, src);
53 ///         }
54 ///         Err(e) => println!("couldn't receive a datagram: {}", e)
55 ///     }
56 ///     drop(socket); // close the socket
57 /// }
58 /// ```
59 pub struct UdpSocket {
60     inner: UdpSocketImp,
61 }
62
63 impl UdpSocket {
64     /// Creates a UDP socket from the given address.
65     ///
66     /// Address type can be any implementor of `ToSocketAddr` trait. See its
67     /// documentation for concrete examples.
68     pub fn bind<A: ToSocketAddr>(addr: A) -> IoResult<UdpSocket> {
69         super::with_addresses(addr, |addr| {
70             UdpSocketImp::bind(addr).map(|s| UdpSocket { inner: s })
71         })
72     }
73
74     /// Receives data from the socket. On success, returns the number of bytes
75     /// read and the address from whence the data came.
76     pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
77         self.inner.recv_from(buf)
78     }
79
80     /// Sends data on the socket to the given address. Returns nothing on
81     /// success.
82     ///
83     /// Address type can be any implementer of `ToSocketAddr` trait. See its
84     /// documentation for concrete examples.
85     pub fn send_to<A: ToSocketAddr>(&mut self, buf: &[u8], addr: A) -> IoResult<()> {
86         super::with_addresses(addr, |addr| self.inner.send_to(buf, addr))
87     }
88
89     /// Returns the socket address that this socket was created from.
90     pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
91         self.inner.socket_name()
92     }
93
94     /// Joins a multicast IP address (becomes a member of it)
95     #[experimental]
96     pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
97         self.inner.join_multicast(multi)
98     }
99
100     /// Leaves a multicast IP address (drops membership from it)
101     #[experimental]
102     pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
103         self.inner.leave_multicast(multi)
104     }
105
106     /// Set the multicast loop flag to the specified value
107     ///
108     /// This lets multicast packets loop back to local sockets (if enabled)
109     #[experimental]
110     pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> {
111         self.inner.set_multicast_loop(on)
112     }
113
114     /// Sets the multicast TTL
115     #[experimental]
116     pub fn set_multicast_ttl(&mut self, ttl: int) -> IoResult<()> {
117         self.inner.multicast_time_to_live(ttl)
118     }
119
120     /// Sets this socket's TTL
121     #[experimental]
122     pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> {
123         self.inner.time_to_live(ttl)
124     }
125
126     /// Sets the broadcast flag on or off
127     #[experimental]
128     pub fn set_broadcast(&mut self, broadcast: bool) -> IoResult<()> {
129         self.inner.set_broadcast(broadcast)
130     }
131
132     /// Sets the read/write timeout for this socket.
133     ///
134     /// For more information, see `TcpStream::set_timeout`
135     #[experimental = "the timeout argument may change in type and value"]
136     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
137         self.inner.set_timeout(timeout_ms)
138     }
139
140     /// Sets the read timeout for this socket.
141     ///
142     /// For more information, see `TcpStream::set_timeout`
143     #[experimental = "the timeout argument may change in type and value"]
144     pub fn set_read_timeout(&mut self, timeout_ms: Option<u64>) {
145         self.inner.set_read_timeout(timeout_ms)
146     }
147
148     /// Sets the write timeout for this socket.
149     ///
150     /// For more information, see `TcpStream::set_timeout`
151     #[experimental = "the timeout argument may change in type and value"]
152     pub fn set_write_timeout(&mut self, timeout_ms: Option<u64>) {
153         self.inner.set_write_timeout(timeout_ms)
154     }
155 }
156
157 impl Clone for UdpSocket {
158     /// Creates a new handle to this UDP socket, allowing for simultaneous
159     /// reads and writes of the socket.
160     ///
161     /// The underlying UDP socket will not be closed until all handles to the
162     /// socket have been deallocated. Two concurrent reads will not receive
163     /// the same data. Instead, the first read will receive the first packet
164     /// received, and the second read will receive the second packet.
165     fn clone(&self) -> UdpSocket {
166         UdpSocket {
167             inner: self.inner.clone(),
168         }
169     }
170 }
171
172 impl sys_common::AsInner<UdpSocketImp> for UdpSocket {
173     fn as_inner(&self) -> &UdpSocketImp {
174         &self.inner
175     }
176 }
177
178 #[cfg(test)]
179 #[allow(experimental)]
180 mod test {
181     use prelude::v1::*;
182
183     use sync::mpsc::channel;
184     use io::net::ip::*;
185     use io::test::*;
186     use io::{IoError, TimedOut, PermissionDenied, ShortWrite};
187     use super::*;
188     use thread::Thread;
189
190     // FIXME #11530 this fails on android because tests are run as root
191     #[cfg_attr(any(windows, target_os = "android"), ignore)]
192     #[test]
193     fn bind_error() {
194         let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
195         match UdpSocket::bind(addr) {
196             Ok(..) => panic!(),
197             Err(e) => assert_eq!(e.kind, PermissionDenied),
198         }
199     }
200
201     #[test]
202     fn socket_smoke_test_ip4() {
203         let server_ip = next_test_ip4();
204         let client_ip = next_test_ip4();
205         let (tx1, rx1) = channel();
206         let (tx2, rx2) = channel();
207
208         let _t = Thread::spawn(move|| {
209             match UdpSocket::bind(client_ip) {
210                 Ok(ref mut client) => {
211                     rx1.recv().unwrap();
212                     client.send_to(&[99], server_ip).unwrap()
213                 }
214                 Err(..) => panic!()
215             }
216             tx2.send(()).unwrap();
217         });
218
219         match UdpSocket::bind(server_ip) {
220             Ok(ref mut server) => {
221                 tx1.send(()).unwrap();
222                 let mut buf = [0];
223                 match server.recv_from(&mut buf) {
224                     Ok((nread, src)) => {
225                         assert_eq!(nread, 1);
226                         assert_eq!(buf[0], 99);
227                         assert_eq!(src, client_ip);
228                     }
229                     Err(..) => panic!()
230                 }
231             }
232             Err(..) => panic!()
233         }
234         rx2.recv().unwrap();
235     }
236
237     #[test]
238     fn socket_smoke_test_ip6() {
239         let server_ip = next_test_ip6();
240         let client_ip = next_test_ip6();
241         let (tx, rx) = channel::<()>();
242
243         let _t = Thread::spawn(move|| {
244             match UdpSocket::bind(client_ip) {
245                 Ok(ref mut client) => {
246                     rx.recv().unwrap();
247                     client.send_to(&[99], server_ip).unwrap()
248                 }
249                 Err(..) => panic!()
250             }
251         });
252
253         match UdpSocket::bind(server_ip) {
254             Ok(ref mut server) => {
255                 tx.send(()).unwrap();
256                 let mut buf = [0];
257                 match server.recv_from(&mut buf) {
258                     Ok((nread, src)) => {
259                         assert_eq!(nread, 1);
260                         assert_eq!(buf[0], 99);
261                         assert_eq!(src, client_ip);
262                     }
263                     Err(..) => panic!()
264                 }
265             }
266             Err(..) => panic!()
267         }
268     }
269
270     pub fn socket_name(addr: SocketAddr) {
271         let server = UdpSocket::bind(addr);
272
273         assert!(server.is_ok());
274         let mut server = server.unwrap();
275
276         // Make sure socket_name gives
277         // us the socket we binded to.
278         let so_name = server.socket_name();
279         assert!(so_name.is_ok());
280         assert_eq!(addr, so_name.unwrap());
281     }
282
283     #[test]
284     fn socket_name_ip4() {
285         socket_name(next_test_ip4());
286     }
287
288     #[test]
289     fn socket_name_ip6() {
290         socket_name(next_test_ip6());
291     }
292
293     #[test]
294     fn udp_clone_smoke() {
295         let addr1 = next_test_ip4();
296         let addr2 = next_test_ip4();
297         let mut sock1 = UdpSocket::bind(addr1).unwrap();
298         let sock2 = UdpSocket::bind(addr2).unwrap();
299
300         let _t = Thread::spawn(move|| {
301             let mut sock2 = sock2;
302             let mut buf = [0, 0];
303             assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1)));
304             assert_eq!(buf[0], 1);
305             sock2.send_to(&[2], addr1).unwrap();
306         });
307
308         let sock3 = sock1.clone();
309
310         let (tx1, rx1) = channel();
311         let (tx2, rx2) = channel();
312         let _t = Thread::spawn(move|| {
313             let mut sock3 = sock3;
314             rx1.recv().unwrap();
315             sock3.send_to(&[1], addr2).unwrap();
316             tx2.send(()).unwrap();
317         });
318         tx1.send(()).unwrap();
319         let mut buf = [0, 0];
320         assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2)));
321         rx2.recv().unwrap();
322     }
323
324     #[test]
325     fn udp_clone_two_read() {
326         let addr1 = next_test_ip4();
327         let addr2 = next_test_ip4();
328         let mut sock1 = UdpSocket::bind(addr1).unwrap();
329         let sock2 = UdpSocket::bind(addr2).unwrap();
330         let (tx1, rx) = channel();
331         let tx2 = tx1.clone();
332
333         let _t = Thread::spawn(move|| {
334             let mut sock2 = sock2;
335             sock2.send_to(&[1], addr1).unwrap();
336             rx.recv().unwrap();
337             sock2.send_to(&[2], addr1).unwrap();
338             rx.recv().unwrap();
339         });
340
341         let sock3 = sock1.clone();
342
343         let (done, rx) = channel();
344         let _t = Thread::spawn(move|| {
345             let mut sock3 = sock3;
346             let mut buf = [0, 0];
347             sock3.recv_from(&mut buf).unwrap();
348             tx2.send(()).unwrap();
349             done.send(()).unwrap();
350         });
351         let mut buf = [0, 0];
352         sock1.recv_from(&mut buf).unwrap();
353         tx1.send(()).unwrap();
354
355         rx.recv().unwrap();
356     }
357
358     #[test]
359     fn udp_clone_two_write() {
360         let addr1 = next_test_ip4();
361         let addr2 = next_test_ip4();
362         let mut sock1 = UdpSocket::bind(addr1).unwrap();
363         let sock2 = UdpSocket::bind(addr2).unwrap();
364
365         let (tx, rx) = channel();
366         let (serv_tx, serv_rx) = channel();
367
368         let _t = Thread::spawn(move|| {
369             let mut sock2 = sock2;
370             let mut buf = [0, 1];
371
372             rx.recv().unwrap();
373             match sock2.recv_from(&mut buf) {
374                 Ok(..) => {}
375                 Err(e) => panic!("failed receive: {}", e),
376             }
377             serv_tx.send(()).unwrap();
378         });
379
380         let sock3 = sock1.clone();
381
382         let (done, rx) = channel();
383         let tx2 = tx.clone();
384         let _t = Thread::spawn(move|| {
385             let mut sock3 = sock3;
386             match sock3.send_to(&[1], addr2) {
387                 Ok(..) => { let _ = tx2.send(()); }
388                 Err(..) => {}
389             }
390             done.send(()).unwrap();
391         });
392         match sock1.send_to(&[2], addr2) {
393             Ok(..) => { let _ = tx.send(()); }
394             Err(..) => {}
395         }
396         drop(tx);
397
398         rx.recv().unwrap();
399         serv_rx.recv().unwrap();
400     }
401
402     #[cfg(not(windows))] // FIXME #17553
403     #[test]
404     fn recv_from_timeout() {
405         let addr1 = next_test_ip4();
406         let addr2 = next_test_ip4();
407         let mut a = UdpSocket::bind(addr1).unwrap();
408         let a2 = UdpSocket::bind(addr2).unwrap();
409
410         let (tx, rx) = channel();
411         let (tx2, rx2) = channel();
412         let _t = Thread::spawn(move|| {
413             let mut a = a2;
414             assert_eq!(a.recv_from(&mut [0]), Ok((1, addr1)));
415             assert_eq!(a.send_to(&[0], addr1), Ok(()));
416             rx.recv().unwrap();
417             assert_eq!(a.send_to(&[0], addr1), Ok(()));
418
419             tx2.send(()).unwrap();
420         });
421
422         // Make sure that reads time out, but writes can continue
423         a.set_read_timeout(Some(20));
424         assert_eq!(a.recv_from(&mut [0]).err().unwrap().kind, TimedOut);
425         assert_eq!(a.recv_from(&mut [0]).err().unwrap().kind, TimedOut);
426         assert_eq!(a.send_to(&[0], addr2), Ok(()));
427
428         // Cloned handles should be able to block
429         let mut a2 = a.clone();
430         assert_eq!(a2.recv_from(&mut [0]), Ok((1, addr2)));
431
432         // Clearing the timeout should allow for receiving
433         a.set_timeout(None);
434         tx.send(()).unwrap();
435         assert_eq!(a2.recv_from(&mut [0]), Ok((1, addr2)));
436
437         // Make sure the child didn't die
438         rx2.recv().unwrap();
439     }
440
441     #[test]
442     fn send_to_timeout() {
443         let addr1 = next_test_ip4();
444         let addr2 = next_test_ip4();
445         let mut a = UdpSocket::bind(addr1).unwrap();
446         let _b = UdpSocket::bind(addr2).unwrap();
447
448         a.set_write_timeout(Some(1000));
449         for _ in range(0u, 100) {
450             match a.send_to(&[0;4*1024], addr2) {
451                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
452                 Err(IoError { kind: TimedOut, .. }) => break,
453                 Err(e) => panic!("other error: {}", e),
454             }
455         }
456     }
457 }