xref: /webrtc/ice/src/agent/agent_gather_test.rs (revision 5d8fe953)
1 use super::agent_vnet_test::*;
2 use super::*;
3 use crate::udp_mux::{UDPMuxDefault, UDPMuxParams};
4 use crate::util::*;
5 
6 use ipnet::IpNet;
7 use std::str::FromStr;
8 use tokio::net::UdpSocket;
9 use util::vnet::*;
10 
11 #[tokio::test]
test_vnet_gather_no_local_ip_address() -> Result<()>12 async fn test_vnet_gather_no_local_ip_address() -> Result<()> {
13     let vnet = Arc::new(net::Net::new(Some(net::NetConfig::default())));
14 
15     let a = Agent::new(AgentConfig {
16         net: Some(Arc::clone(&vnet)),
17         ..Default::default()
18     })
19     .await?;
20 
21     let local_ips = local_interfaces(
22         &vnet,
23         &a.interface_filter,
24         &a.ip_filter,
25         &[NetworkType::Udp4],
26     )
27     .await;
28     assert!(local_ips.is_empty(), "should return no local IP");
29 
30     a.close().await?;
31 
32     Ok(())
33 }
34 
35 #[tokio::test]
test_vnet_gather_dynamic_ip_address() -> Result<()>36 async fn test_vnet_gather_dynamic_ip_address() -> Result<()> {
37     let cider = "1.2.3.0/24";
38     let ipnet = IpNet::from_str(cider).map_err(|e| Error::Other(e.to_string()))?;
39 
40     let r = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
41         cidr: cider.to_owned(),
42         ..Default::default()
43     })?));
44     let nw = Arc::new(net::Net::new(Some(net::NetConfig::default())));
45     connect_net2router(&nw, &r).await?;
46 
47     let a = Agent::new(AgentConfig {
48         net: Some(Arc::clone(&nw)),
49         ..Default::default()
50     })
51     .await?;
52 
53     let local_ips =
54         local_interfaces(&nw, &a.interface_filter, &a.ip_filter, &[NetworkType::Udp4]).await;
55     assert!(!local_ips.is_empty(), "should have one local IP");
56 
57     for ip in &local_ips {
58         if ip.is_loopback() {
59             panic!("should not return loopback IP");
60         }
61         if !ipnet.contains(ip) {
62             panic!("{ip} should be contained in the CIDR {ipnet}");
63         }
64     }
65 
66     a.close().await?;
67 
68     Ok(())
69 }
70 
71 #[tokio::test]
test_vnet_gather_listen_udp() -> Result<()>72 async fn test_vnet_gather_listen_udp() -> Result<()> {
73     let cider = "1.2.3.0/24";
74     let r = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
75         cidr: cider.to_owned(),
76         ..Default::default()
77     })?));
78     let nw = Arc::new(net::Net::new(Some(net::NetConfig::default())));
79     connect_net2router(&nw, &r).await?;
80 
81     let a = Agent::new(AgentConfig {
82         net: Some(Arc::clone(&nw)),
83         ..Default::default()
84     })
85     .await?;
86 
87     let local_ips =
88         local_interfaces(&nw, &a.interface_filter, &a.ip_filter, &[NetworkType::Udp4]).await;
89     assert!(!local_ips.is_empty(), "should have one local IP");
90 
91     for ip in local_ips {
92         let _ = listen_udp_in_port_range(&nw, 0, 0, SocketAddr::new(ip, 0)).await?;
93 
94         let result = listen_udp_in_port_range(&nw, 4999, 5000, SocketAddr::new(ip, 0)).await;
95         assert!(
96             result.is_err(),
97             "listenUDP with invalid port range did not return ErrPort"
98         );
99 
100         let conn = listen_udp_in_port_range(&nw, 5000, 5000, SocketAddr::new(ip, 0)).await?;
101         let port = conn.local_addr()?.port();
102         assert_eq!(
103             port, 5000,
104             "listenUDP with port restriction of 5000 listened on incorrect port ({port})"
105         );
106     }
107 
108     a.close().await?;
109 
110     Ok(())
111 }
112 
113 #[tokio::test]
test_vnet_gather_with_nat_1to1_as_host_candidates() -> Result<()>114 async fn test_vnet_gather_with_nat_1to1_as_host_candidates() -> Result<()> {
115     let external_ip0 = "1.2.3.4";
116     let external_ip1 = "1.2.3.5";
117     let local_ip0 = "10.0.0.1";
118     let local_ip1 = "10.0.0.2";
119     let map0 = format!("{external_ip0}/{local_ip0}");
120     let map1 = format!("{external_ip1}/{local_ip1}");
121 
122     let wan = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
123         cidr: "1.2.3.0/24".to_owned(),
124         ..Default::default()
125     })?));
126 
127     let lan = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
128         cidr: "10.0.0.0/24".to_owned(),
129         static_ips: vec![map0.clone(), map1.clone()],
130         nat_type: Some(nat::NatType {
131             mode: nat::NatMode::Nat1To1,
132             ..Default::default()
133         }),
134         ..Default::default()
135     })?));
136 
137     connect_router2router(&lan, &wan).await?;
138 
139     let nw = Arc::new(net::Net::new(Some(net::NetConfig {
140         static_ips: vec![local_ip0.to_owned(), local_ip1.to_owned()],
141         ..Default::default()
142     })));
143 
144     connect_net2router(&nw, &lan).await?;
145 
146     let a = Agent::new(AgentConfig {
147         network_types: vec![NetworkType::Udp4],
148         nat_1to1_ips: vec![map0.clone(), map1.clone()],
149         net: Some(Arc::clone(&nw)),
150         ..Default::default()
151     })
152     .await?;
153 
154     let (done_tx, mut done_rx) = mpsc::channel::<()>(1);
155     let done_tx = Arc::new(Mutex::new(Some(done_tx)));
156     a.on_candidate(Box::new(
157         move |c: Option<Arc<dyn Candidate + Send + Sync>>| {
158             let done_tx_clone = Arc::clone(&done_tx);
159             Box::pin(async move {
160                 if c.is_none() {
161                     let mut tx = done_tx_clone.lock().await;
162                     tx.take();
163                 }
164             })
165         },
166     ));
167 
168     a.gather_candidates()?;
169 
170     log::debug!("wait for gathering is done...");
171     let _ = done_rx.recv().await;
172     log::debug!("gathering is done");
173 
174     let candidates = a.get_local_candidates().await?;
175     assert_eq!(candidates.len(), 2, "There must be two candidates");
176 
177     let mut laddrs = vec![];
178     for candi in &candidates {
179         if let Some(conn) = candi.get_conn() {
180             let laddr = conn.local_addr()?;
181             assert_eq!(
182                 candi.port(),
183                 laddr.port(),
184                 "Unexpected candidate port: {}",
185                 candi.port()
186             );
187             laddrs.push(laddr);
188         }
189     }
190 
191     if candidates[0].address() == external_ip0 {
192         assert_eq!(
193             candidates[1].address(),
194             external_ip1,
195             "Unexpected candidate IP: {}",
196             candidates[1].address()
197         );
198         assert_eq!(
199             laddrs[0].ip().to_string(),
200             local_ip0,
201             "Unexpected listen IP: {}",
202             laddrs[0].ip()
203         );
204         assert_eq!(
205             laddrs[1].ip().to_string(),
206             local_ip1,
207             "Unexpected listen IP: {}",
208             laddrs[1].ip()
209         );
210     } else if candidates[0].address() == external_ip1 {
211         assert_eq!(
212             candidates[1].address(),
213             external_ip0,
214             "Unexpected candidate IP: {}",
215             candidates[1].address()
216         );
217         assert_eq!(
218             laddrs[0].ip().to_string(),
219             local_ip1,
220             "Unexpected listen IP: {}",
221             laddrs[0].ip(),
222         );
223         assert_eq!(
224             laddrs[1].ip().to_string(),
225             local_ip0,
226             "Unexpected listen IP: {}",
227             laddrs[1].ip(),
228         )
229     }
230 
231     a.close().await?;
232 
233     Ok(())
234 }
235 
236 #[tokio::test]
test_vnet_gather_with_nat_1to1_as_srflx_candidates() -> Result<()>237 async fn test_vnet_gather_with_nat_1to1_as_srflx_candidates() -> Result<()> {
238     let wan = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
239         cidr: "1.2.3.0/24".to_owned(),
240         ..Default::default()
241     })?));
242 
243     let lan = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
244         cidr: "10.0.0.0/24".to_owned(),
245         static_ips: vec!["1.2.3.4/10.0.0.1".to_owned()],
246         nat_type: Some(nat::NatType {
247             mode: nat::NatMode::Nat1To1,
248             ..Default::default()
249         }),
250         ..Default::default()
251     })?));
252 
253     connect_router2router(&lan, &wan).await?;
254 
255     let nw = Arc::new(net::Net::new(Some(net::NetConfig {
256         static_ips: vec!["10.0.0.1".to_owned()],
257         ..Default::default()
258     })));
259 
260     connect_net2router(&nw, &lan).await?;
261 
262     let a = Agent::new(AgentConfig {
263         network_types: vec![NetworkType::Udp4],
264         nat_1to1_ips: vec!["1.2.3.4".to_owned()],
265         nat_1to1_ip_candidate_type: CandidateType::ServerReflexive,
266         net: Some(nw),
267         ..Default::default()
268     })
269     .await?;
270 
271     let (done_tx, mut done_rx) = mpsc::channel::<()>(1);
272     let done_tx = Arc::new(Mutex::new(Some(done_tx)));
273     a.on_candidate(Box::new(
274         move |c: Option<Arc<dyn Candidate + Send + Sync>>| {
275             let done_tx_clone = Arc::clone(&done_tx);
276             Box::pin(async move {
277                 if c.is_none() {
278                     let mut tx = done_tx_clone.lock().await;
279                     tx.take();
280                 }
281             })
282         },
283     ));
284 
285     a.gather_candidates()?;
286 
287     log::debug!("wait for gathering is done...");
288     let _ = done_rx.recv().await;
289     log::debug!("gathering is done");
290 
291     let candidates = a.get_local_candidates().await?;
292     assert_eq!(candidates.len(), 2, "There must be two candidates");
293 
294     let mut candi_host = None;
295     let mut candi_srflx = None;
296 
297     for candidate in candidates {
298         match candidate.candidate_type() {
299             CandidateType::Host => {
300                 candi_host = Some(candidate);
301             }
302             CandidateType::ServerReflexive => {
303                 candi_srflx = Some(candidate);
304             }
305             _ => {
306                 panic!("Unexpected candidate type");
307             }
308         }
309     }
310 
311     assert!(candi_host.is_some(), "should not be nil");
312     assert_eq!("10.0.0.1", candi_host.unwrap().address(), "should match");
313     assert!(candi_srflx.is_some(), "should not be nil");
314     assert_eq!("1.2.3.4", candi_srflx.unwrap().address(), "should match");
315 
316     a.close().await?;
317 
318     Ok(())
319 }
320 
321 #[tokio::test]
test_vnet_gather_with_interface_filter() -> Result<()>322 async fn test_vnet_gather_with_interface_filter() -> Result<()> {
323     let r = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
324         cidr: "1.2.3.0/24".to_owned(),
325         ..Default::default()
326     })?));
327     let nw = Arc::new(net::Net::new(Some(net::NetConfig::default())));
328     connect_net2router(&nw, &r).await?;
329 
330     //"InterfaceFilter should exclude the interface"
331     {
332         let a = Agent::new(AgentConfig {
333             net: Some(Arc::clone(&nw)),
334             interface_filter: Arc::new(Some(Box::new(|_: &str| -> bool {
335                 //assert_eq!("eth0", interface_name);
336                 false
337             }))),
338             ..Default::default()
339         })
340         .await?;
341 
342         let local_ips =
343             local_interfaces(&nw, &a.interface_filter, &a.ip_filter, &[NetworkType::Udp4]).await;
344         assert!(
345             local_ips.is_empty(),
346             "InterfaceFilter should have excluded everything"
347         );
348 
349         a.close().await?;
350     }
351 
352     //"InterfaceFilter should not exclude the interface"
353     {
354         let a = Agent::new(AgentConfig {
355             net: Some(Arc::clone(&nw)),
356             interface_filter: Arc::new(Some(Box::new(|interface_name: &str| -> bool {
357                 "eth0" == interface_name
358             }))),
359             ..Default::default()
360         })
361         .await?;
362 
363         let local_ips =
364             local_interfaces(&nw, &a.interface_filter, &a.ip_filter, &[NetworkType::Udp4]).await;
365         assert_eq!(
366             local_ips.len(),
367             1,
368             "InterfaceFilter should not have excluded everything"
369         );
370 
371         a.close().await?;
372     }
373 
374     Ok(())
375 }
376 
377 #[tokio::test]
test_vnet_gather_turn_connection_leak() -> Result<()>378 async fn test_vnet_gather_turn_connection_leak() -> Result<()> {
379     let turn_server_url = Url {
380         scheme: SchemeType::Turn,
381         host: VNET_STUN_SERVER_IP.to_owned(),
382         port: VNET_STUN_SERVER_PORT,
383         username: "user".to_owned(),
384         password: "pass".to_owned(),
385         proto: ProtoType::Udp,
386     };
387 
388     // buildVNet with a Symmetric NATs for both LANs
389     let nat_type = nat::NatType {
390         mapping_behavior: nat::EndpointDependencyType::EndpointAddrPortDependent,
391         filtering_behavior: nat::EndpointDependencyType::EndpointAddrPortDependent,
392         ..Default::default()
393     };
394 
395     let v = build_vnet(nat_type, nat_type).await?;
396 
397     let cfg0 = AgentConfig {
398         urls: vec![turn_server_url.clone()],
399         network_types: supported_network_types(),
400         multicast_dns_mode: MulticastDnsMode::Disabled,
401         nat_1to1_ips: vec![VNET_GLOBAL_IPA.to_owned()],
402         net: Some(Arc::clone(&v.net0)),
403         ..Default::default()
404     };
405 
406     let a_agent = Agent::new(cfg0).await?;
407 
408     {
409         let agent_internal = Arc::clone(&a_agent.internal);
410         Agent::gather_candidates_relay(
411             vec![turn_server_url.clone()],
412             Arc::clone(&v.net0),
413             agent_internal,
414         )
415         .await;
416     }
417 
418     // Assert relay conn leak on close.
419     a_agent.close().await?;
420     v.close().await?;
421 
422     Ok(())
423 }
424 
425 #[tokio::test]
test_vnet_gather_muxed_udp() -> Result<()>426 async fn test_vnet_gather_muxed_udp() -> Result<()> {
427     let udp_socket = UdpSocket::bind("0.0.0.0:0").await?;
428     let udp_mux = UDPMuxDefault::new(UDPMuxParams::new(udp_socket));
429 
430     let lan = Arc::new(Mutex::new(router::Router::new(router::RouterConfig {
431         cidr: "10.0.0.0/24".to_owned(),
432         nat_type: Some(nat::NatType {
433             mode: nat::NatMode::Nat1To1,
434             ..Default::default()
435         }),
436         ..Default::default()
437     })?));
438 
439     let nw = Arc::new(net::Net::new(Some(net::NetConfig {
440         static_ips: vec!["10.0.0.1".to_owned()],
441         ..Default::default()
442     })));
443 
444     connect_net2router(&nw, &lan).await?;
445 
446     let a = Agent::new(AgentConfig {
447         network_types: vec![NetworkType::Udp4],
448         nat_1to1_ips: vec!["1.2.3.4".to_owned()],
449         net: Some(nw),
450         udp_network: UDPNetwork::Muxed(udp_mux),
451         ..Default::default()
452     })
453     .await?;
454 
455     let (done_tx, mut done_rx) = mpsc::channel::<()>(1);
456     let done_tx = Arc::new(Mutex::new(Some(done_tx)));
457     a.on_candidate(Box::new(
458         move |c: Option<Arc<dyn Candidate + Send + Sync>>| {
459             let done_tx_clone = Arc::clone(&done_tx);
460             Box::pin(async move {
461                 if c.is_none() {
462                     let mut tx = done_tx_clone.lock().await;
463                     tx.take();
464                 }
465             })
466         },
467     ));
468 
469     a.gather_candidates()?;
470 
471     log::debug!("wait for gathering is done...");
472     let _ = done_rx.recv().await;
473     log::debug!("gathering is done");
474 
475     let candidates = a.get_local_candidates().await?;
476     assert_eq!(candidates.len(), 1, "There must be a single candidate");
477 
478     let candi = &candidates[0];
479     let laddr = candi.get_conn().unwrap().local_addr()?;
480     assert_eq!(candi.address(), "1.2.3.4");
481     assert_eq!(
482         candi.port(),
483         laddr.port(),
484         "Unexpected candidate port: {}",
485         candi.port()
486     );
487 
488     Ok(())
489 }
490