[go: up one dir, main page]

net2/
udp.rs

1// Copyright 2015 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
11use std::cell::RefCell;
12use std::fmt;
13use std::io;
14use std::net::{ToSocketAddrs, UdpSocket};
15
16use IntoInner;
17use socket::Socket;
18use sys::c;
19
20/// An "in progress" UDP socket which has not yet been connected.
21///
22/// Allows configuration of a socket before the socket is connected.
23pub struct UdpBuilder {
24    socket: RefCell<Option<Socket>>,
25}
26
27impl UdpBuilder {
28    /// Constructs a new UdpBuilder with the `AF_INET` domain, the `SOCK_DGRAM`
29    /// type, and with a protocol argument of 0.
30    ///
31    /// Note that passing other kinds of flags or arguments can be done through
32    /// the `FromRaw{Fd,Socket}` implementation.
33    pub fn new_v4() -> io::Result<UdpBuilder> {
34        Socket::new(c::AF_INET, c::SOCK_DGRAM).map(::FromInner::from_inner)
35    }
36
37    /// Constructs a new UdpBuilder with the `AF_INET6` domain, the `SOCK_DGRAM`
38    /// type, and with a protocol argument of 0.
39    ///
40    /// Note that passing other kinds of flags or arguments can be done through
41    /// the `FromRaw{Fd,Socket}` implementation.
42    pub fn new_v6() -> io::Result<UdpBuilder> {
43        Socket::new(c::AF_INET6, c::SOCK_DGRAM).map(::FromInner::from_inner)
44    }
45
46    /// Binds this socket to the specified address.
47    ///
48    /// This function directly corresponds to the bind(2) function on Windows
49    /// and Unix.
50    pub fn bind<T>(&self, addr: T) -> io::Result<UdpSocket>
51        where T: ToSocketAddrs
52    {
53        try!(self.with_socket(|sock| {
54            let addr = try!(::one_addr(addr));
55            sock.bind(&addr)
56        }));
57        Ok(self.socket.borrow_mut().take().unwrap().into_inner().into_udp_socket())
58    }
59
60    fn with_socket<F>(&self, f: F) -> io::Result<()>
61        where F: FnOnce(&Socket) -> io::Result<()>
62    {
63        match *self.socket.borrow() {
64            Some(ref s) => f(s),
65            None => Err(io::Error::new(io::ErrorKind::Other,
66                                       "builder has already finished its socket")),
67        }
68    }
69}
70
71impl fmt::Debug for UdpBuilder {
72    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        write!(f, "UdpBuilder {{ socket: {:?} }}",
74               self.socket.borrow().as_ref().unwrap())
75    }
76}
77
78impl ::AsInner for UdpBuilder {
79    type Inner = RefCell<Option<Socket>>;
80    fn as_inner(&self) -> &RefCell<Option<Socket>> { &self.socket }
81}
82
83impl ::FromInner for UdpBuilder {
84    type Inner = Socket;
85    fn from_inner(sock: Socket) -> UdpBuilder {
86        UdpBuilder { socket: RefCell::new(Some(sock)) }
87    }
88}
89