]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/net/udp.rs
libstd: Document the following modules:
[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 //! A UDP connection implements the `Reader` and `Writer` traits.
19
20 use clone::Clone;
21 use result::{Ok, Err};
22 use io::net::ip::SocketAddr;
23 use io::{Reader, Writer, IoResult};
24 use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
25
26 /// A User Datagram Protocol socket.
27 pub struct UdpSocket {
28     priv obj: ~RtioUdpSocket
29 }
30
31 impl UdpSocket {
32     /// Creates a UDP socket from the given socket address.
33     pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
34         LocalIo::maybe_raise(|io| {
35             io.udp_bind(addr).map(|s| UdpSocket { obj: s })
36         })
37     }
38
39     /// Receives data from the socket. On success, returns the number of bytes
40     /// read and the address from whence the data came.
41     pub fn recvfrom(&mut self, buf: &mut [u8])
42                     -> IoResult<(uint, SocketAddr)> {
43         self.obj.recvfrom(buf)
44     }
45
46     /// Sends data on the socket to the given address. Returns nothing on
47     /// success.
48     pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
49         self.obj.sendto(buf, dst)
50     }
51
52     /// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
53     /// traits to receive and send data from the same address. This transfers
54     /// ownership of the socket to the stream.
55     ///
56     /// Note that this call does not perform any actual network communication,
57     /// because UDP is a datagram protocol.
58     pub fn connect(self, other: SocketAddr) -> UdpStream {
59         UdpStream {
60             socket: self,
61             connected_to: other,
62         }
63     }
64
65     /// Returns the socket address that this socket was created from.
66     pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
67         self.obj.socket_name()
68     }
69 }
70
71 impl Clone for UdpSocket {
72     /// Creates a new handle to this UDP socket, allowing for simultaneous
73     /// reads and writes of the socket.
74     ///
75     /// The underlying UDP socket will not be closed until all handles to the
76     /// socket have been deallocated. Two concurrent reads will not receive
77     /// the same data. Instead, the first read will receive the first packet
78     /// received, and the second read will receive the second packet.
79     fn clone(&self) -> UdpSocket {
80         UdpSocket {
81             obj: self.obj.clone(),
82         }
83     }
84 }
85
86 /// A type that allows convenient usage of a UDP stream connected to one
87 /// address via the `Reader` and `Writer` traits.
88 pub struct UdpStream {
89     priv socket: UdpSocket,
90     priv connected_to: SocketAddr
91 }
92
93 impl UdpStream {
94     /// Allows access to the underlying UDP socket owned by this stream. This
95     /// is useful to, for example, use the socket to send data to hosts other
96     /// than the one that this stream is connected to.
97     pub fn as_socket<T>(&mut self, f: |&mut UdpSocket| -> T) -> T {
98         f(&mut self.socket)
99     }
100
101     /// Consumes this UDP stream and returns out the underlying socket.
102     pub fn disconnect(self) -> UdpSocket {
103         self.socket
104     }
105 }
106
107 impl Reader for UdpStream {
108     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
109         let peer = self.connected_to;
110         self.as_socket(|sock| {
111             match sock.recvfrom(buf) {
112                 Ok((_nread, src)) if src != peer => Ok(0),
113                 Ok((nread, _src)) => Ok(nread),
114                 Err(e) => Err(e),
115             }
116         })
117     }
118 }
119
120 impl Writer for UdpStream {
121     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
122         let connected_to = self.connected_to;
123         self.as_socket(|sock| sock.sendto(buf, connected_to))
124     }
125 }
126
127 #[cfg(test)]
128 mod test {
129     use super::*;
130     use io::net::ip::{SocketAddr};
131
132     // FIXME #11530 this fails on android because tests are run as root
133     iotest!(fn bind_error() {
134         let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
135         match UdpSocket::bind(addr) {
136             Ok(..) => fail!(),
137             Err(e) => assert_eq!(e.kind, PermissionDenied),
138         }
139     } #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))])
140
141     iotest!(fn socket_smoke_test_ip4() {
142         let server_ip = next_test_ip4();
143         let client_ip = next_test_ip4();
144         let (tx1, rx1) = channel();
145         let (tx2, rx2) = channel();
146
147         spawn(proc() {
148             match UdpSocket::bind(client_ip) {
149                 Ok(ref mut client) => {
150                     rx1.recv();
151                     client.sendto([99], server_ip).unwrap()
152                 }
153                 Err(..) => fail!()
154             }
155             tx2.send(());
156         });
157
158         match UdpSocket::bind(server_ip) {
159             Ok(ref mut server) => {
160                 tx1.send(());
161                 let mut buf = [0];
162                 match server.recvfrom(buf) {
163                     Ok((nread, src)) => {
164                         assert_eq!(nread, 1);
165                         assert_eq!(buf[0], 99);
166                         assert_eq!(src, client_ip);
167                     }
168                     Err(..) => fail!()
169                 }
170             }
171             Err(..) => fail!()
172         }
173         rx2.recv();
174     })
175
176     iotest!(fn socket_smoke_test_ip6() {
177         let server_ip = next_test_ip6();
178         let client_ip = next_test_ip6();
179         let (tx, rx) = channel::<()>();
180
181         spawn(proc() {
182             match UdpSocket::bind(client_ip) {
183                 Ok(ref mut client) => {
184                     rx.recv();
185                     client.sendto([99], server_ip).unwrap()
186                 }
187                 Err(..) => fail!()
188             }
189         });
190
191         match UdpSocket::bind(server_ip) {
192             Ok(ref mut server) => {
193                 tx.send(());
194                 let mut buf = [0];
195                 match server.recvfrom(buf) {
196                     Ok((nread, src)) => {
197                         assert_eq!(nread, 1);
198                         assert_eq!(buf[0], 99);
199                         assert_eq!(src, client_ip);
200                     }
201                     Err(..) => fail!()
202                 }
203             }
204             Err(..) => fail!()
205         }
206     })
207
208     iotest!(fn stream_smoke_test_ip4() {
209         let server_ip = next_test_ip4();
210         let client_ip = next_test_ip4();
211         let (tx1, rx1) = channel();
212         let (tx2, rx2) = channel();
213
214         spawn(proc() {
215             match UdpSocket::bind(client_ip) {
216                 Ok(client) => {
217                     let client = ~client;
218                     let mut stream = client.connect(server_ip);
219                     rx1.recv();
220                     stream.write([99]).unwrap();
221                 }
222                 Err(..) => fail!()
223             }
224             tx2.send(());
225         });
226
227         match UdpSocket::bind(server_ip) {
228             Ok(server) => {
229                 let server = ~server;
230                 let mut stream = server.connect(client_ip);
231                 tx1.send(());
232                 let mut buf = [0];
233                 match stream.read(buf) {
234                     Ok(nread) => {
235                         assert_eq!(nread, 1);
236                         assert_eq!(buf[0], 99);
237                     }
238                     Err(..) => fail!()
239                 }
240             }
241             Err(..) => fail!()
242         }
243         rx2.recv();
244     })
245
246     iotest!(fn stream_smoke_test_ip6() {
247         let server_ip = next_test_ip6();
248         let client_ip = next_test_ip6();
249         let (tx1, rx1) = channel();
250         let (tx2, rx2) = channel();
251
252         spawn(proc() {
253             match UdpSocket::bind(client_ip) {
254                 Ok(client) => {
255                     let client = ~client;
256                     let mut stream = client.connect(server_ip);
257                     rx1.recv();
258                     stream.write([99]).unwrap();
259                 }
260                 Err(..) => fail!()
261             }
262             tx2.send(());
263         });
264
265         match UdpSocket::bind(server_ip) {
266             Ok(server) => {
267                 let server = ~server;
268                 let mut stream = server.connect(client_ip);
269                 tx1.send(());
270                 let mut buf = [0];
271                 match stream.read(buf) {
272                     Ok(nread) => {
273                         assert_eq!(nread, 1);
274                         assert_eq!(buf[0], 99);
275                     }
276                     Err(..) => fail!()
277                 }
278             }
279             Err(..) => fail!()
280         }
281         rx2.recv();
282     })
283
284     pub fn socket_name(addr: SocketAddr) {
285         let server = UdpSocket::bind(addr);
286
287         assert!(server.is_ok());
288         let mut server = server.unwrap();
289
290         // Make sure socket_name gives
291         // us the socket we binded to.
292         let so_name = server.socket_name();
293         assert!(so_name.is_ok());
294         assert_eq!(addr, so_name.unwrap());
295     }
296
297     iotest!(fn socket_name_ip4() {
298         socket_name(next_test_ip4());
299     })
300
301     iotest!(fn socket_name_ip6() {
302         socket_name(next_test_ip6());
303     })
304
305     iotest!(fn udp_clone_smoke() {
306         let addr1 = next_test_ip4();
307         let addr2 = next_test_ip4();
308         let mut sock1 = UdpSocket::bind(addr1).unwrap();
309         let sock2 = UdpSocket::bind(addr2).unwrap();
310
311         spawn(proc() {
312             let mut sock2 = sock2;
313             let mut buf = [0, 0];
314             assert_eq!(sock2.recvfrom(buf), Ok((1, addr1)));
315             assert_eq!(buf[0], 1);
316             sock2.sendto([2], addr1).unwrap();
317         });
318
319         let sock3 = sock1.clone();
320
321         let (tx1, rx1) = channel();
322         let (tx2, rx2) = channel();
323         spawn(proc() {
324             let mut sock3 = sock3;
325             rx1.recv();
326             sock3.sendto([1], addr2).unwrap();
327             tx2.send(());
328         });
329         tx1.send(());
330         let mut buf = [0, 0];
331         assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
332         rx2.recv();
333     })
334
335     iotest!(fn udp_clone_two_read() {
336         let addr1 = next_test_ip4();
337         let addr2 = next_test_ip4();
338         let mut sock1 = UdpSocket::bind(addr1).unwrap();
339         let sock2 = UdpSocket::bind(addr2).unwrap();
340         let (tx1, rx) = channel();
341         let tx2 = tx1.clone();
342
343         spawn(proc() {
344             let mut sock2 = sock2;
345             sock2.sendto([1], addr1).unwrap();
346             rx.recv();
347             sock2.sendto([2], addr1).unwrap();
348             rx.recv();
349         });
350
351         let sock3 = sock1.clone();
352
353         let (done, rx) = channel();
354         spawn(proc() {
355             let mut sock3 = sock3;
356             let mut buf = [0, 0];
357             sock3.recvfrom(buf).unwrap();
358             tx2.send(());
359             done.send(());
360         });
361         let mut buf = [0, 0];
362         sock1.recvfrom(buf).unwrap();
363         tx1.send(());
364
365         rx.recv();
366     })
367
368     iotest!(fn udp_clone_two_write() {
369         let addr1 = next_test_ip4();
370         let addr2 = next_test_ip4();
371         let mut sock1 = UdpSocket::bind(addr1).unwrap();
372         let sock2 = UdpSocket::bind(addr2).unwrap();
373
374         let (tx, rx) = channel();
375         let (serv_tx, serv_rx) = channel();
376
377         spawn(proc() {
378             let mut sock2 = sock2;
379             let mut buf = [0, 1];
380
381             rx.recv();
382             match sock2.recvfrom(buf) {
383                 Ok(..) => {}
384                 Err(e) => fail!("failed receive: {}", e),
385             }
386             serv_tx.send(());
387         });
388
389         let sock3 = sock1.clone();
390
391         let (done, rx) = channel();
392         let tx2 = tx.clone();
393         spawn(proc() {
394             let mut sock3 = sock3;
395             match sock3.sendto([1], addr2) {
396                 Ok(..) => { let _ = tx2.try_send(()); }
397                 Err(..) => {}
398             }
399             done.send(());
400         });
401         match sock1.sendto([2], addr2) {
402             Ok(..) => { let _ = tx.try_send(()); }
403             Err(..) => {}
404         }
405         drop(tx);
406
407         rx.recv();
408         serv_rx.recv();
409     })
410 }