1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use std::io::{self, ErrorKind};
use std::net::{ToSocketAddrs, UdpSocket};
use std::net::{SocketAddr, IpAddr};
#[cfg(not(windows))]
use net2::unix::UnixUdpBuilderExt;
use net2::UdpBuilder;
pub mod connector;
pub mod packet;
pub mod sender;
#[derive(Copy, Clone)]
pub enum IpVersionMode {
V4Only,
V6Only,
Any,
}
impl IpVersionMode {
pub fn from_addr<A: ToSocketAddrs>(addr: A) -> io::Result<Self> {
match try!(addr_from_trait(addr)) {
SocketAddr::V4(_) => Ok(IpVersionMode::V4Only),
SocketAddr::V6(_) => Ok(IpVersionMode::V6Only),
}
}
}
pub fn addr_from_trait<A: ToSocketAddrs>(addr: A) -> io::Result<SocketAddr> {
let mut sock_iter = try!(addr.to_socket_addrs());
match sock_iter.next() {
Some(n) => Ok(n),
None => Err(io::Error::new(ErrorKind::InvalidInput, "Failed To Parse SocketAddr")),
}
}
pub fn bind_reuse<A: ToSocketAddrs>(local_addr: A) -> io::Result<UdpSocket> {
let local_addr = try!(addr_from_trait(local_addr));
let builder = match local_addr {
SocketAddr::V4(_) => try!(UdpBuilder::new_v4()),
SocketAddr::V6(_) => try!(UdpBuilder::new_v6()),
};
try!(reuse_port(&builder));
builder.bind(local_addr)
}
#[cfg(windows)]
fn reuse_port(builder: &UdpBuilder) -> io::Result<()> {
try!(builder.reuse_address(true));
Ok(())
}
#[cfg(not(windows))]
fn reuse_port(builder: &UdpBuilder) -> io::Result<()> {
try!(builder.reuse_address(true));
try!(builder.reuse_port(true));
Ok(())
}
pub fn join_multicast(sock: &UdpSocket, iface: &SocketAddr, mcast_addr: &IpAddr) -> io::Result<()> {
match (iface, mcast_addr) {
(&SocketAddr::V4(ref i), &IpAddr::V4(ref m)) => sock.join_multicast_v4(m, i.ip()),
(&SocketAddr::V6(ref i), &IpAddr::V6(ref m)) => sock.join_multicast_v6(m, i.scope_id()),
_ => {
Err(io::Error::new(ErrorKind::InvalidInput,
"Multicast And Interface Addresses Are Not The Same Version"))
}
}
}
#[allow(dead_code)]
pub fn leave_multicast(sock: &UdpSocket, iface_addr: &SocketAddr, mcast_addr: &SocketAddr) -> io::Result<()> {
match (iface_addr, mcast_addr) {
(&SocketAddr::V4(ref i), &SocketAddr::V4(ref m)) => sock.leave_multicast_v4(m.ip(), i.ip()),
(&SocketAddr::V6(ref i), &SocketAddr::V6(ref m)) => sock.leave_multicast_v6(m.ip(), i.scope_id()),
_ => {
Err(io::Error::new(ErrorKind::InvalidInput,
"Multicast And Interface Addresses Are Not The Same Version"))
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn positive_addr_from_trait() {
super::addr_from_trait("192.168.0.1:0").unwrap();
}
#[test]
#[should_panic]
fn negative_addr_from_trait() {
super::addr_from_trait("192.168.0.1").unwrap();
}
}