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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::io;
use std::net::SocketAddr;
use net::connector::UdpConnector;
use net::IpVersionMode;
mod notify;
mod search;
mod ssdp;
pub mod listen;
pub mod multicast;
use get_if_addrs;
pub use message::multicast::Multicast;
pub use message::search::{SearchRequest, SearchResponse, SearchListener};
pub use message::notify::{NotifyMessage, NotifyListener};
pub use message::listen::Listen;
pub const UPNP_MULTICAST_IPV4_ADDR: &'static str = "239.255.255.250";
pub const UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR: &'static str = "FF02::C";
pub const UPNP_MULTICAST_PORT: u16 = 1900;
pub const UPNP_MULTICAST_TTL: u32 = 2;
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub enum MessageType {
Notify,
Search,
Response,
}
#[derive(Clone)]
pub struct Config {
pub ipv4_addr: String,
pub ipv6_addr: String,
pub port: u16,
pub ttl: u32,
pub mode: IpVersionMode,
}
impl Config {
pub fn new() -> Self {
Default::default()
}
pub fn set_ipv4_addr<S: Into<String>>(mut self, value: S) -> Self {
self.ipv4_addr = value.into();
self
}
pub fn set_ipv6_addr<S: Into<String>>(mut self, value: S) -> Self {
self.ipv6_addr = value.into();
self
}
pub fn set_port(mut self, value: u16) -> Self {
self.port = value;
self
}
pub fn set_ttl(mut self, value: u32) -> Self {
self.ttl = value;
self
}
pub fn set_mode(mut self, value: IpVersionMode) -> Self {
self.mode = value;
self
}
}
impl Default for Config {
fn default() -> Self {
Config {
ipv4_addr: UPNP_MULTICAST_IPV4_ADDR.to_string(),
ipv6_addr: UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR.to_string(),
port: UPNP_MULTICAST_PORT,
ttl: UPNP_MULTICAST_TTL,
mode: IpVersionMode::Any,
}
}
}
fn all_local_connectors(multicast_ttl: Option<u32>, filter: &IpVersionMode) -> io::Result<Vec<UdpConnector>> {
trace!("Fetching all local connectors");
map_local(|&addr| match (filter, addr) {
(&IpVersionMode::V4Only, SocketAddr::V4(n)) |
(&IpVersionMode::Any, SocketAddr::V4(n)) => {
Ok(Some(try!(UdpConnector::new((*n.ip(), 0), multicast_ttl))))
}
(&IpVersionMode::V6Only, SocketAddr::V6(n)) |
(&IpVersionMode::Any, SocketAddr::V6(n)) => Ok(Some(try!(UdpConnector::new(n, multicast_ttl)))),
_ => Ok(None),
})
}
fn map_local<F, R>(mut f: F) -> io::Result<Vec<R>>
where F: FnMut(&SocketAddr) -> io::Result<Option<R>>
{
let addrs_iter = try!(get_local_addrs());
let mut obj_list = Vec::with_capacity(addrs_iter.len());
for addr in addrs_iter {
trace!("Found {}", addr);
match addr {
SocketAddr::V4(n) if !n.ip().is_loopback() => {
if let Some(x) = try!(f(&addr)) {
obj_list.push(x);
}
}
SocketAddr::V6(n) if !n.ip().is_loopback() && !n.ip().is_global() => {
if let Some(x) = try!(f(&addr)) {
obj_list.push(x);
}
}
_ => (),
}
}
Ok(obj_list)
}
fn get_local_addrs() -> io::Result<Vec<SocketAddr>> {
let iface_iter = try!(get_if_addrs::get_if_addrs()).into_iter();
Ok(iface_iter.filter_map(|iface| Some(SocketAddr::new(iface.addr.ip(), 0)))
.collect())
}